| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_TRACKED_OBJECTS_H_ | 5 #ifndef BASE_TRACKED_OBJECTS_H_ |
| 6 #define BASE_TRACKED_OBJECTS_H_ | 6 #define BASE_TRACKED_OBJECTS_H_ |
| 7 | 7 |
| 8 #include <map> | 8 #include <map> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <stack> | 10 #include <stack> |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 // instances for each combination of birth thread, death thread, and location, | 147 // instances for each combination of birth thread, death thread, and location, |
| 148 // along with the count of such lifetimes. We gather such data into a | 148 // along with the count of such lifetimes. We gather such data into a |
| 149 // TaskSnapshot instances, so that such instances can be sorted and | 149 // TaskSnapshot instances, so that such instances can be sorted and |
| 150 // aggregated (and remain frozen during our processing). | 150 // aggregated (and remain frozen during our processing). |
| 151 // | 151 // |
| 152 // Profiling consists of phases. The concrete phase in the sequence of phases | 152 // Profiling consists of phases. The concrete phase in the sequence of phases |
| 153 // is identified by its 0-based index. | 153 // is identified by its 0-based index. |
| 154 // | 154 // |
| 155 // The ProcessDataPhaseSnapshot struct is a serialized representation of the | 155 // The ProcessDataPhaseSnapshot struct is a serialized representation of the |
| 156 // list of ThreadData objects for a process for a concrete profiling phase. It | 156 // list of ThreadData objects for a process for a concrete profiling phase. It |
| 157 // holds a set of TaskSnapshots and tracks parent/child relationships for the | 157 // holds a set of TaskSnapshots. The statistics in a snapshot are gathered |
| 158 // executed tasks. The statistics in a snapshot are gathered asynhcronously | 158 // asynhcronously relative to their ongoing updates. |
| 159 // relative to their ongoing updates. | |
| 160 // It is possible, though highly unlikely, that stats could be incorrectly | 159 // It is possible, though highly unlikely, that stats could be incorrectly |
| 161 // recorded by this process (all data is held in 32 bit ints, but we are not | 160 // recorded by this process (all data is held in 32 bit ints, but we are not |
| 162 // atomically collecting all data, so we could have count that does not, for | 161 // atomically collecting all data, so we could have count that does not, for |
| 163 // example, match with the number of durations we accumulated). The advantage | 162 // example, match with the number of durations we accumulated). The advantage |
| 164 // to having fast (non-atomic) updates of the data outweighs the minimal risk of | 163 // to having fast (non-atomic) updates of the data outweighs the minimal risk of |
| 165 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, | 164 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, |
| 166 // not the underlying and ongoing statistic). In contrast, pointer data that | 165 // not the underlying and ongoing statistic). In contrast, pointer data that |
| 167 // is accessed during snapshotting is completely invariant, and hence is | 166 // is accessed during snapshotting is completely invariant, and hence is |
| 168 // perfectly acquired (i.e., no potential corruption, and no risk of a bad | 167 // perfectly acquired (i.e., no potential corruption, and no risk of a bad |
| 169 // memory reference). | 168 // memory reference). |
| 170 // | 169 // |
| 171 // TODO(jar): We can implement a Snapshot system that *tries* to grab the | 170 // TODO(jar): We can implement a Snapshot system that *tries* to grab the |
| 172 // snapshots on the source threads *when* they have MessageLoops available | 171 // snapshots on the source threads *when* they have MessageLoops available |
| 173 // (worker threads don't have message loops generally, and hence gathering from | 172 // (worker threads don't have message loops generally, and hence gathering from |
| 174 // them will continue to be asynchronous). We had an implementation of this in | 173 // them will continue to be asynchronous). We had an implementation of this in |
| 175 // the past, but the difficulty is dealing with message loops being terminated. | 174 // the past, but the difficulty is dealing with message loops being terminated. |
| 176 // We can *try* to spam the available threads via some message loop proxy to | 175 // We can *try* to spam the available threads via some message loop proxy to |
| 177 // achieve this feat, and it *might* be valuable when we are collecting data | 176 // achieve this feat, and it *might* be valuable when we are collecting data |
| 178 // for upload via UMA (where correctness of data may be more significant than | 177 // for upload via UMA (where correctness of data may be more significant than |
| 179 // for a single screen of about:profiler). | 178 // for a single screen of about:profiler). |
| 180 // | 179 // |
| 181 // TODO(jar): We should support (optionally) the recording of parent-child | |
| 182 // relationships for tasks. This should be done by detecting what tasks are | |
| 183 // Born during the running of a parent task. The resulting data can be used by | |
| 184 // a smarter profiler to aggregate the cost of a series of child tasks into | |
| 185 // the ancestor task. It can also be used to illuminate what child or parent is | |
| 186 // related to each task. | |
| 187 // | |
| 188 // TODO(jar): We need to store DataCollections, and provide facilities for | 180 // TODO(jar): We need to store DataCollections, and provide facilities for |
| 189 // taking the difference between two gathered DataCollections. For now, we're | 181 // taking the difference between two gathered DataCollections. For now, we're |
| 190 // just adding a hack that Reset()s to zero all counts and stats. This is also | 182 // just adding a hack that Reset()s to zero all counts and stats. This is also |
| 191 // done in a slightly thread-unsafe fashion, as the resetting is done | 183 // done in a slightly thread-unsafe fashion, as the resetting is done |
| 192 // asynchronously relative to ongoing updates (but all data is 32 bit in size). | 184 // asynchronously relative to ongoing updates (but all data is 32 bit in size). |
| 193 // For basic profiling, this will work "most of the time," and should be | 185 // For basic profiling, this will work "most of the time," and should be |
| 194 // sufficient... but storing away DataCollections is the "right way" to do this. | 186 // sufficient... but storing away DataCollections is the "right way" to do this. |
| 195 // We'll accomplish this via JavaScript storage of snapshots, and then we'll | 187 // We'll accomplish this via JavaScript storage of snapshots, and then we'll |
| 196 // remove the Reset() methods. We may also need a short-term-max value in | 188 // remove the Reset() methods. We may also need a short-term-max value in |
| 197 // DeathData that is reset (as synchronously as possible) during each snapshot. | 189 // DeathData that is reset (as synchronously as possible) during each snapshot. |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 // Map from profiling phase number to the process-wide snapshotted | 415 // Map from profiling phase number to the process-wide snapshotted |
| 424 // representation of the list of ThreadData objects that died during the given | 416 // representation of the list of ThreadData objects that died during the given |
| 425 // phase. | 417 // phase. |
| 426 typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshotMap; | 418 typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshotMap; |
| 427 | 419 |
| 428 class BASE_EXPORT ThreadData { | 420 class BASE_EXPORT ThreadData { |
| 429 public: | 421 public: |
| 430 // Current allowable states of the tracking system. The states can vary | 422 // Current allowable states of the tracking system. The states can vary |
| 431 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. | 423 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. |
| 432 enum Status { | 424 enum Status { |
| 433 UNINITIALIZED, // PRistine, link-time state before running. | 425 UNINITIALIZED, // Pristine, link-time state before running. |
| 434 DORMANT_DURING_TESTS, // Only used during testing. | 426 DORMANT_DURING_TESTS, // Only used during testing. |
| 435 DEACTIVATED, // No longer recording profiling. | 427 DEACTIVATED, // No longer recording profiling. |
| 436 PROFILING_ACTIVE, // Recording profiles (no parent-child links). | 428 PROFILING_ACTIVE, // Recording profiles. |
| 437 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. | 429 STATUS_LAST = PROFILING_ACTIVE |
| 438 STATUS_LAST = PROFILING_CHILDREN_ACTIVE | |
| 439 }; | 430 }; |
| 440 | 431 |
| 441 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; | 432 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; |
| 442 typedef std::map<const Births*, DeathData> DeathMap; | 433 typedef std::map<const Births*, DeathData> DeathMap; |
| 443 typedef std::pair<const Births*, const Births*> ParentChildPair; | |
| 444 typedef std::set<ParentChildPair> ParentChildSet; | |
| 445 typedef std::stack<const Births*> ParentStack; | |
| 446 | 434 |
| 447 // Initialize the current thread context with a new instance of ThreadData. | 435 // Initialize the current thread context with a new instance of ThreadData. |
| 448 // This is used by all threads that have names, and should be explicitly | 436 // This is used by all threads that have names, and should be explicitly |
| 449 // set *before* any births on the threads have taken place. It is generally | 437 // set *before* any births on the threads have taken place. It is generally |
| 450 // only used by the message loop, which has a well defined thread name. | 438 // only used by the message loop, which has a well defined thread name. |
| 451 static void InitializeThreadContext(const std::string& suggested_name); | 439 static void InitializeThreadContext(const std::string& suggested_name); |
| 452 | 440 |
| 453 // Using Thread Local Store, find the current instance for collecting data. | 441 // Using Thread Local Store, find the current instance for collecting data. |
| 454 // If an instance does not exist, construct one (and remember it for use on | 442 // If an instance does not exist, construct one (and remember it for use on |
| 455 // this thread. | 443 // this thread. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 const TaskStopwatch& stopwatch); | 495 const TaskStopwatch& stopwatch); |
| 508 | 496 |
| 509 const std::string& thread_name() const { return thread_name_; } | 497 const std::string& thread_name() const { return thread_name_; } |
| 510 | 498 |
| 511 // Initializes all statics if needed (this initialization call should be made | 499 // Initializes all statics if needed (this initialization call should be made |
| 512 // while we are single threaded). Returns false if unable to initialize. | 500 // while we are single threaded). Returns false if unable to initialize. |
| 513 static bool Initialize(); | 501 static bool Initialize(); |
| 514 | 502 |
| 515 // Sets internal status_. | 503 // Sets internal status_. |
| 516 // If |status| is false, then status_ is set to DEACTIVATED. | 504 // If |status| is false, then status_ is set to DEACTIVATED. |
| 517 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or | 505 // If |status| is true, then status_ is set to PROFILING_ACTIVE. |
| 518 // PROFILING_CHILDREN_ACTIVE. | 506 // If it fails to initialize the TLS slot, this function will return false. |
| 519 // If tracking is not compiled in, this function will return false. | |
| 520 // If parent-child tracking is not compiled in, then an attempt to set the | |
| 521 // status to PROFILING_CHILDREN_ACTIVE will only result in a status of | |
| 522 // PROFILING_ACTIVE (i.e., it can't be set to a higher level than what is | |
| 523 // compiled into the binary, and parent-child tracking at the | |
| 524 // PROFILING_CHILDREN_ACTIVE level might not be compiled in). | |
| 525 static bool InitializeAndSetTrackingStatus(Status status); | 507 static bool InitializeAndSetTrackingStatus(Status status); |
| 526 | 508 |
| 527 static Status status(); | 509 static Status status(); |
| 528 | 510 |
| 529 // Indicate if any sort of profiling is being done (i.e., we are more than | 511 // Indicate if any sort of profiling is being done (i.e., we are more than |
| 530 // DEACTIVATED). | 512 // DEACTIVATED). |
| 531 static bool TrackingStatus(); | 513 static bool TrackingStatus(); |
| 532 | 514 |
| 533 // For testing only, indicate if the status of parent-child tracking is turned | |
| 534 // on. This is currently a compiled option, atop TrackingStatus(). | |
| 535 static bool TrackingParentChildStatus(); | |
| 536 | |
| 537 // Marks a start of a tracked run. It's super fast when tracking is disabled, | |
| 538 // and has some internal side effects when we are tracking, so that we can | |
| 539 // deduce the amount of time accumulated outside of execution of tracked runs. | |
| 540 // The task that will be tracked is passed in as |parent| so that parent-child | |
| 541 // relationships can be (optionally) calculated. | |
| 542 static void PrepareForStartOfRun(const Births* parent); | |
| 543 | |
| 544 // Enables profiler timing. | 515 // Enables profiler timing. |
| 545 static void EnableProfilerTiming(); | 516 static void EnableProfilerTiming(); |
| 546 | 517 |
| 547 // Provide a time function that does nothing (runs fast) when we don't have | 518 // Provide a time function that does nothing (runs fast) when we don't have |
| 548 // the profiler enabled. It will generally be optimized away when it is | 519 // the profiler enabled. It will generally be optimized away when it is |
| 549 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of | 520 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of |
| 550 // the code). | 521 // the code). |
| 551 static TrackedTime Now(); | 522 static TrackedTime Now(); |
| 552 | 523 |
| 553 // Use the function |now| to provide current times, instead of calling the | 524 // Use the function |now| to provide current times, instead of calling the |
| (...skipping 10 matching lines...) Expand all Loading... |
| 564 private: | 535 private: |
| 565 friend class TaskStopwatch; | 536 friend class TaskStopwatch; |
| 566 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it | 537 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it |
| 567 // in production code. | 538 // in production code. |
| 568 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a | 539 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a |
| 569 // better change of optimizing (inlining? etc.) private methods (knowing that | 540 // better change of optimizing (inlining? etc.) private methods (knowing that |
| 570 // there will be no need for an external entry point). | 541 // there will be no need for an external entry point). |
| 571 friend class TrackedObjectsTest; | 542 friend class TrackedObjectsTest; |
| 572 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); | 543 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); |
| 573 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); | 544 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); |
| 574 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); | |
| 575 | 545 |
| 576 typedef std::map<const BirthOnThread*, int> BirthCountMap; | 546 typedef std::map<const BirthOnThread*, int> BirthCountMap; |
| 577 | 547 |
| 578 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> | 548 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> |
| 579 DeathsSnapshot; | 549 DeathsSnapshot; |
| 580 | 550 |
| 581 // Worker thread construction creates a name since there is none. | 551 // Worker thread construction creates a name since there is none. |
| 582 explicit ThreadData(int thread_number); | 552 explicit ThreadData(int thread_number); |
| 583 | 553 |
| 584 // Message loop based construction should provide a name. | 554 // Message loop based construction should provide a name. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 615 // number of births for the task that have not yet been balanced by a death. | 585 // number of births for the task that have not yet been balanced by a death. |
| 616 void SnapshotExecutedTasks(int current_profiling_phase, | 586 void SnapshotExecutedTasks(int current_profiling_phase, |
| 617 PhasedProcessDataSnapshotMap* phased_snapshots, | 587 PhasedProcessDataSnapshotMap* phased_snapshots, |
| 618 BirthCountMap* birth_counts); | 588 BirthCountMap* birth_counts); |
| 619 | 589 |
| 620 // Using our lock, make a copy of the specified maps. This call may be made | 590 // Using our lock, make a copy of the specified maps. This call may be made |
| 621 // on non-local threads, which necessitate the use of the lock to prevent | 591 // on non-local threads, which necessitate the use of the lock to prevent |
| 622 // the map(s) from being reallocated while they are copied. | 592 // the map(s) from being reallocated while they are copied. |
| 623 void SnapshotMaps(int profiling_phase, | 593 void SnapshotMaps(int profiling_phase, |
| 624 BirthMap* birth_map, | 594 BirthMap* birth_map, |
| 625 DeathsSnapshot* deaths, | 595 DeathsSnapshot* deaths); |
| 626 ParentChildSet* parent_child_set); | |
| 627 | 596 |
| 628 // Called for this thread when the current profiling phase, identified by | 597 // Called for this thread when the current profiling phase, identified by |
| 629 // |profiling_phase|, ends. | 598 // |profiling_phase|, ends. |
| 630 void OnProfilingPhaseCompletedOnThread(int profiling_phase); | 599 void OnProfilingPhaseCompletedOnThread(int profiling_phase); |
| 631 | 600 |
| 632 // This method is called by the TLS system when a thread terminates. | 601 // This method is called by the TLS system when a thread terminates. |
| 633 // The argument may be NULL if this thread has never tracked a birth or death. | 602 // The argument may be NULL if this thread has never tracked a birth or death. |
| 634 static void OnThreadTermination(void* thread_data); | 603 static void OnThreadTermination(void* thread_data); |
| 635 | 604 |
| 636 // This method should be called when a worker thread terminates, so that we | 605 // This method should be called when a worker thread terminates, so that we |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 // When a snapshot is needed, this structure can be locked in place for the | 687 // When a snapshot is needed, this structure can be locked in place for the |
| 719 // duration of the snapshotting activity. | 688 // duration of the snapshotting activity. |
| 720 BirthMap birth_map_; | 689 BirthMap birth_map_; |
| 721 | 690 |
| 722 // Similar to birth_map_, this records informations about death of tracked | 691 // Similar to birth_map_, this records informations about death of tracked |
| 723 // instances (i.e., when a tracked instance was destroyed on this thread). | 692 // instances (i.e., when a tracked instance was destroyed on this thread). |
| 724 // It is locked before changing, and hence other threads may access it by | 693 // It is locked before changing, and hence other threads may access it by |
| 725 // locking before reading it. | 694 // locking before reading it. |
| 726 DeathMap death_map_; | 695 DeathMap death_map_; |
| 727 | 696 |
| 728 // A set of parents that created children tasks on this thread. Each pair | |
| 729 // corresponds to potentially non-local Births (location and thread), and a | |
| 730 // local Births (that took place on this thread). | |
| 731 ParentChildSet parent_child_set_; | |
| 732 | |
| 733 // Lock to protect *some* access to BirthMap and DeathMap. The maps are | 697 // Lock to protect *some* access to BirthMap and DeathMap. The maps are |
| 734 // regularly read and written on this thread, but may only be read from other | 698 // regularly read and written on this thread, but may only be read from other |
| 735 // threads. To support this, we acquire this lock if we are writing from this | 699 // threads. To support this, we acquire this lock if we are writing from this |
| 736 // thread, or reading from another thread. For reading from this thread we | 700 // thread, or reading from another thread. For reading from this thread we |
| 737 // don't need a lock, as there is no potential for a conflict since the | 701 // don't need a lock, as there is no potential for a conflict since the |
| 738 // writing is only done from this thread. | 702 // writing is only done from this thread. |
| 739 mutable base::Lock map_lock_; | 703 mutable base::Lock map_lock_; |
| 740 | 704 |
| 741 // The stack of parents that are currently being profiled. This includes only | |
| 742 // tasks that have started a timer recently via PrepareForStartOfRun(), but | |
| 743 // not yet concluded with a NowForEndOfRun(). Usually this stack is one deep, | |
| 744 // but if a scoped region is profiled, or <sigh> a task runs a nested-message | |
| 745 // loop, then the stack can grow larger. Note that we don't try to deduct | |
| 746 // time in nested profiles, as our current timer is based on wall-clock time, | |
| 747 // and not CPU time (and we're hopeful that nested timing won't be a | |
| 748 // significant additional cost). | |
| 749 ParentStack parent_stack_; | |
| 750 | |
| 751 // A random number that we used to select decide which sample to keep as a | 705 // A random number that we used to select decide which sample to keep as a |
| 752 // representative sample in each DeathData instance. We can't start off with | 706 // representative sample in each DeathData instance. We can't start off with |
| 753 // much randomness (because we can't call RandInt() on all our threads), so | 707 // much randomness (because we can't call RandInt() on all our threads), so |
| 754 // we stir in more and more as we go. | 708 // we stir in more and more as we go. |
| 755 uint32 random_number_; | 709 uint32 random_number_; |
| 756 | 710 |
| 757 // Record of what the incarnation_counter_ was when this instance was created. | 711 // Record of what the incarnation_counter_ was when this instance was created. |
| 758 // If the incarnation_counter_ has changed, then we avoid pushing into the | 712 // If the incarnation_counter_ has changed, then we avoid pushing into the |
| 759 // pool (this is only critical in tests which go through multiple | 713 // pool (this is only critical in tests which go through multiple |
| 760 // incarnations). | 714 // incarnations). |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 // state, then is optionally started/stopped, then destructed. | 775 // state, then is optionally started/stopped, then destructed. |
| 822 enum { CREATED, RUNNING, STOPPED } state_; | 776 enum { CREATED, RUNNING, STOPPED } state_; |
| 823 | 777 |
| 824 // Currently running stopwatch that is directly nested in this one, if such | 778 // Currently running stopwatch that is directly nested in this one, if such |
| 825 // stopwatch exists. NULL otherwise. | 779 // stopwatch exists. NULL otherwise. |
| 826 TaskStopwatch* child_; | 780 TaskStopwatch* child_; |
| 827 #endif | 781 #endif |
| 828 }; | 782 }; |
| 829 | 783 |
| 830 //------------------------------------------------------------------------------ | 784 //------------------------------------------------------------------------------ |
| 831 // A snapshotted representation of a (parent, child) task pair, for tracking | |
| 832 // hierarchical profiles. | |
| 833 | |
| 834 struct BASE_EXPORT ParentChildPairSnapshot { | |
| 835 public: | |
| 836 ParentChildPairSnapshot(); | |
| 837 explicit ParentChildPairSnapshot( | |
| 838 const ThreadData::ParentChildPair& parent_child); | |
| 839 ~ParentChildPairSnapshot(); | |
| 840 | |
| 841 BirthOnThreadSnapshot parent; | |
| 842 BirthOnThreadSnapshot child; | |
| 843 }; | |
| 844 | |
| 845 //------------------------------------------------------------------------------ | |
| 846 // A snapshotted representation of the list of ThreadData objects for a process, | 785 // A snapshotted representation of the list of ThreadData objects for a process, |
| 847 // for a single profiling phase. | 786 // for a single profiling phase. |
| 848 | 787 |
| 849 struct BASE_EXPORT ProcessDataPhaseSnapshot { | 788 struct BASE_EXPORT ProcessDataPhaseSnapshot { |
| 850 public: | 789 public: |
| 851 ProcessDataPhaseSnapshot(); | 790 ProcessDataPhaseSnapshot(); |
| 852 ~ProcessDataPhaseSnapshot(); | 791 ~ProcessDataPhaseSnapshot(); |
| 853 | 792 |
| 854 std::vector<TaskSnapshot> tasks; | 793 std::vector<TaskSnapshot> tasks; |
| 855 std::vector<ParentChildPairSnapshot> descendants; | |
| 856 }; | 794 }; |
| 857 | 795 |
| 858 //------------------------------------------------------------------------------ | 796 //------------------------------------------------------------------------------ |
| 859 // A snapshotted representation of the list of ThreadData objects for a process, | 797 // A snapshotted representation of the list of ThreadData objects for a process, |
| 860 // for all profiling phases, including the current one. | 798 // for all profiling phases, including the current one. |
| 861 | 799 |
| 862 struct BASE_EXPORT ProcessDataSnapshot { | 800 struct BASE_EXPORT ProcessDataSnapshot { |
| 863 public: | 801 public: |
| 864 ProcessDataSnapshot(); | 802 ProcessDataSnapshot(); |
| 865 ~ProcessDataSnapshot(); | 803 ~ProcessDataSnapshot(); |
| 866 | 804 |
| 867 PhasedProcessDataSnapshotMap phased_snapshots; | 805 PhasedProcessDataSnapshotMap phased_snapshots; |
| 868 base::ProcessId process_id; | 806 base::ProcessId process_id; |
| 869 }; | 807 }; |
| 870 | 808 |
| 871 } // namespace tracked_objects | 809 } // namespace tracked_objects |
| 872 | 810 |
| 873 #endif // BASE_TRACKED_OBJECTS_H_ | 811 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |