| 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> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/base_export.h" | 15 #include "base/base_export.h" |
| 16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
| 17 #include "base/gtest_prod_util.h" | 17 #include "base/gtest_prod_util.h" |
| 18 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
| 19 #include "base/location.h" | 19 #include "base/location.h" |
| 20 #include "base/process/process_handle.h" |
| 20 #include "base/profiler/alternate_timer.h" | 21 #include "base/profiler/alternate_timer.h" |
| 21 #include "base/profiler/tracked_time.h" | 22 #include "base/profiler/tracked_time.h" |
| 22 #include "base/synchronization/lock.h" | 23 #include "base/synchronization/lock.h" |
| 23 #include "base/threading/thread_local_storage.h" | 24 #include "base/threading/thread_local_storage.h" |
| 24 | 25 |
| 25 namespace base { | 26 namespace base { |
| 26 struct TrackingInfo; | 27 struct TrackingInfo; |
| 27 } | 28 } |
| 28 | 29 |
| 29 // TrackedObjects provides a database of stats about objects (generally Tasks) | 30 // TrackedObjects provides a database of stats about objects (generally Tasks) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 // (3) the snapshotted data. | 140 // (3) the snapshotted data. |
| 140 // | 141 // |
| 141 // For a given birth location, information about births is spread across data | 142 // For a given birth location, information about births is spread across data |
| 142 // structures that are asynchronously changing on various threads. For | 143 // structures that are asynchronously changing on various threads. For |
| 143 // serialization and display purposes, we need to construct TaskSnapshot | 144 // serialization and display purposes, we need to construct TaskSnapshot |
| 144 // instances for each combination of birth thread, death thread, and location, | 145 // instances for each combination of birth thread, death thread, and location, |
| 145 // along with the count of such lifetimes. We gather such data into a | 146 // along with the count of such lifetimes. We gather such data into a |
| 146 // TaskSnapshot instances, so that such instances can be sorted and | 147 // TaskSnapshot instances, so that such instances can be sorted and |
| 147 // aggregated (and remain frozen during our processing). | 148 // aggregated (and remain frozen during our processing). |
| 148 // | 149 // |
| 149 // The ProcessDataSnapshot struct is a serialized representation of the list | 150 // Profiling consists of phases. The concrete phase in the sequence of phases is |
| 150 // of ThreadData objects for a process. It holds a set of TaskSnapshots | 151 // identified by its 0-based index. |
| 151 // and tracks parent/child relationships for the executed tasks. The statistics | 152 // |
| 152 // in a snapshot are gathered asynhcronously relative to their ongoing updates. | 153 // The ProcessDataPhaseSnapshot struct is a serialized representation of the |
| 154 // list of ThreadData objects for a process for a concrete profiling phase. It |
| 155 // holds a set of TaskSnapshots and tracks parent/child relationships for the |
| 156 // executed tasks. The statistics in a snapshot are gathered asynhcronously |
| 157 // relative to their ongoing updates. |
| 153 // It is possible, though highly unlikely, that stats could be incorrectly | 158 // It is possible, though highly unlikely, that stats could be incorrectly |
| 154 // recorded by this process (all data is held in 32 bit ints, but we are not | 159 // recorded by this process (all data is held in 32 bit ints, but we are not |
| 155 // atomically collecting all data, so we could have count that does not, for | 160 // atomically collecting all data, so we could have count that does not, for |
| 156 // example, match with the number of durations we accumulated). The advantage | 161 // example, match with the number of durations we accumulated). The advantage |
| 157 // to having fast (non-atomic) updates of the data outweighs the minimal risk of | 162 // to having fast (non-atomic) updates of the data outweighs the minimal risk of |
| 158 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, | 163 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, |
| 159 // not the underlying and ongoing statistic). In contrast, pointer data that | 164 // not the underlying and ongoing statistic). In contrast, pointer data that |
| 160 // is accessed during snapshotting is completely invariant, and hence is | 165 // is accessed during snapshotting is completely invariant, and hence is |
| 161 // perfectly acquired (i.e., no potential corruption, and no risk of a bad | 166 // perfectly acquired (i.e., no potential corruption, and no risk of a bad |
| 162 // memory reference). | 167 // memory reference). |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 std::string death_thread_name; | 339 std::string death_thread_name; |
| 335 }; | 340 }; |
| 336 | 341 |
| 337 //------------------------------------------------------------------------------ | 342 //------------------------------------------------------------------------------ |
| 338 // For each thread, we have a ThreadData that stores all tracking info generated | 343 // For each thread, we have a ThreadData that stores all tracking info generated |
| 339 // on this thread. This prevents the need for locking as data accumulates. | 344 // on this thread. This prevents the need for locking as data accumulates. |
| 340 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. | 345 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. |
| 341 // We also have a linked list of ThreadData instances, and that list is used to | 346 // We also have a linked list of ThreadData instances, and that list is used to |
| 342 // harvest data from all existing instances. | 347 // harvest data from all existing instances. |
| 343 | 348 |
| 349 struct ProcessDataPhaseSnapshot; |
| 350 // Map from profiling phase number to the process-wide snapshotted |
| 351 // representation of the list of ThreadData objects that died during the given |
| 352 // phase. |
| 353 typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshotMap; |
| 344 struct ProcessDataSnapshot; | 354 struct ProcessDataSnapshot; |
| 345 class BASE_EXPORT TaskStopwatch; | 355 class BASE_EXPORT TaskStopwatch; |
| 346 | 356 |
| 347 class BASE_EXPORT ThreadData { | 357 class BASE_EXPORT ThreadData { |
| 348 public: | 358 public: |
| 349 // Current allowable states of the tracking system. The states can vary | 359 // Current allowable states of the tracking system. The states can vary |
| 350 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. | 360 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. |
| 351 enum Status { | 361 enum Status { |
| 352 UNINITIALIZED, // PRistine, link-time state before running. | 362 UNINITIALIZED, // PRistine, link-time state before running. |
| 353 DORMANT_DURING_TESTS, // Only used during testing. | 363 DORMANT_DURING_TESTS, // Only used during testing. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 368 // set *before* any births on the threads have taken place. It is generally | 378 // set *before* any births on the threads have taken place. It is generally |
| 369 // only used by the message loop, which has a well defined thread name. | 379 // only used by the message loop, which has a well defined thread name. |
| 370 static void InitializeThreadContext(const std::string& suggested_name); | 380 static void InitializeThreadContext(const std::string& suggested_name); |
| 371 | 381 |
| 372 // Using Thread Local Store, find the current instance for collecting data. | 382 // Using Thread Local Store, find the current instance for collecting data. |
| 373 // If an instance does not exist, construct one (and remember it for use on | 383 // If an instance does not exist, construct one (and remember it for use on |
| 374 // this thread. | 384 // this thread. |
| 375 // This may return NULL if the system is disabled for any reason. | 385 // This may return NULL if the system is disabled for any reason. |
| 376 static ThreadData* Get(); | 386 static ThreadData* Get(); |
| 377 | 387 |
| 378 // Fills |process_data| with all the recursive results in our process. | 388 // Fills |process_data_snapshot| with phased snapshots of all profiling |
| 379 static void Snapshot(ProcessDataSnapshot* process_data); | 389 // phases, including the current one. |
| 390 static void Snapshot(ProcessDataSnapshot* process_data_snapshot); |
| 380 | 391 |
| 381 // Finds (or creates) a place to count births from the given location in this | 392 // Finds (or creates) a place to count births from the given location in this |
| 382 // thread, and increment that tally. | 393 // thread, and increment that tally. |
| 383 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. | 394 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. |
| 384 static Births* TallyABirthIfActive(const Location& location); | 395 static Births* TallyABirthIfActive(const Location& location); |
| 385 | 396 |
| 386 // Records the end of a timed run of an object. The |completed_task| contains | 397 // Records the end of a timed run of an object. The |completed_task| contains |
| 387 // a pointer to a Births, the time_posted, and a delayed_start_time if any. | 398 // a pointer to a Births, the time_posted, and a delayed_start_time if any. |
| 388 // The |start_of_run| indicates when we started to perform the run of the | 399 // The |start_of_run| indicates when we started to perform the run of the |
| 389 // task. The delayed_start_time is non-null for tasks that were posted as | 400 // task. The delayed_start_time is non-null for tasks that were posted as |
| 390 // delayed tasks, and it indicates when the task should have run (i.e., when | 401 // delayed tasks, and it indicates when the task should have run (i.e., when |
| 391 // it should have posted out of the timer queue, and into the work queue. | 402 // it should have posted out of the timer queue, and into the work queue. |
| 392 // The |end_of_run| was just obtained by a call to Now() (just after the task | 403 // The |end_of_run| was just obtained by a call to Now() (just after the task |
| 393 // finished). It is provided as an argument to help with testing. | 404 // finished). It is provided as an argument to help with testing. |
| 394 static void TallyRunOnNamedThreadIfTracking( | 405 static void TallyRunOnNamedThreadIfTracking( |
| 395 const base::TrackingInfo& completed_task, | 406 const base::TrackingInfo& completed_task, |
| 396 const TaskStopwatch& stopwatch); | 407 const TaskStopwatch& stopwatch); |
| 397 | 408 |
| 398 // Record the end of a timed run of an object. The |birth| is the record for | 409 // Record the end of a timed run of an object. The |birth| is the record for |
| 399 // the instance, the |time_posted| records that instant, which is presumed to | 410 // the instance, the |time_posted| records that instant, which is presumed to |
| 400 // be when the task was posted into a queue to run on a worker thread. | 411 // be when the task was posted into a queue to run on a worker thread. |
| 401 // The |start_of_run| is when the worker thread started to perform the run of | 412 // The |start_of_run| is when the worker thread started to perform the run of |
| 402 // the task. | 413 // the task. |
| 403 // The |end_of_run| was just obtained by a call to Now() (just after the task | 414 // The |end_of_run| was just obtained by a call to Now() (just after the task |
| 404 // finished). | 415 // finished). |
| 405 static void TallyRunOnWorkerThreadIfTracking( | 416 static void TallyRunOnWorkerThreadIfTracking(const Births* birth, |
| 406 const Births* birth, | 417 const TrackedTime& time_posted, |
| 407 const TrackedTime& time_posted, | 418 const TaskStopwatch& stopwatch); |
| 408 const TaskStopwatch& stopwatch); | |
| 409 | 419 |
| 410 // Record the end of execution in region, generally corresponding to a scope | 420 // Record the end of execution in region, generally corresponding to a scope |
| 411 // being exited. | 421 // being exited. |
| 412 static void TallyRunInAScopedRegionIfTracking( | 422 static void TallyRunInAScopedRegionIfTracking(const Births* birth, |
| 413 const Births* birth, | 423 const TaskStopwatch& stopwatch); |
| 414 const TaskStopwatch& stopwatch); | |
| 415 | 424 |
| 416 const std::string& thread_name() const { return thread_name_; } | 425 const std::string& thread_name() const { return thread_name_; } |
| 417 | 426 |
| 418 // Initializes all statics if needed (this initialization call should be made | 427 // Initializes all statics if needed (this initialization call should be made |
| 419 // while we are single threaded). Returns false if unable to initialize. | 428 // while we are single threaded). Returns false if unable to initialize. |
| 420 static bool Initialize(); | 429 static bool Initialize(); |
| 421 | 430 |
| 422 // Sets internal status_. | 431 // Sets internal status_. |
| 423 // If |status| is false, then status_ is set to DEACTIVATED. | 432 // If |status| is false, then status_ is set to DEACTIVATED. |
| 424 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or | 433 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 Births* TallyABirth(const Location& location); | 515 Births* TallyABirth(const Location& location); |
| 507 | 516 |
| 508 // Find a place to record a death on this thread. | 517 // Find a place to record a death on this thread. |
| 509 void TallyADeath(const Births& birth, | 518 void TallyADeath(const Births& birth, |
| 510 int32 queue_duration, | 519 int32 queue_duration, |
| 511 const TaskStopwatch& stopwatch); | 520 const TaskStopwatch& stopwatch); |
| 512 | 521 |
| 513 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData | 522 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData |
| 514 // instance. Also updates the |birth_counts| tally for each task to keep | 523 // instance. Also updates the |birth_counts| tally for each task to keep |
| 515 // track of the number of living instances of the task. | 524 // track of the number of living instances of the task. |
| 516 static void SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data, | 525 static void SnapshotAllExecutedTasks( |
| 517 BirthCountMap* birth_counts); | 526 ProcessDataPhaseSnapshot* process_data_phase, |
| 527 BirthCountMap* birth_counts); |
| 528 |
| 529 // Fills |process_data_phase| with all the recursive results in our process. |
| 530 static void SnapshotCurrentPhase( |
| 531 ProcessDataPhaseSnapshot* process_data_phase); |
| 518 | 532 |
| 519 // Snapshots (under a lock) the profiled data for the tasks for this thread | 533 // Snapshots (under a lock) the profiled data for the tasks for this thread |
| 520 // and writes all of the executed tasks' data -- i.e. the data for the tasks | 534 // and writes all of the executed tasks' data -- i.e. the data for the tasks |
| 521 // with with entries in the death_map_ -- into |process_data|. Also updates | 535 // with with entries in the death_map_ -- into |process_data_phase|. Also |
| 522 // the |birth_counts| tally for each task to keep track of the number of | 536 // updates the |birth_counts| tally for each task to keep track of the number |
| 523 // living instances of the task -- that is, each task maps to the number of | 537 // of living instances of the task -- that is, each task maps to the number of |
| 524 // births for the task that have not yet been balanced by a death. | 538 // births for the task that have not yet been balanced by a death. |
| 525 void SnapshotExecutedTasks(ProcessDataSnapshot* process_data, | 539 void SnapshotExecutedTasks(ProcessDataPhaseSnapshot* process_data_phase, |
| 526 BirthCountMap* birth_counts); | 540 BirthCountMap* birth_counts); |
| 527 | 541 |
| 528 // Using our lock, make a copy of the specified maps. This call may be made | 542 // Using our lock, make a copy of the specified maps. This call may be made |
| 529 // on non-local threads, which necessitate the use of the lock to prevent | 543 // on non-local threads, which necessitate the use of the lock to prevent |
| 530 // the map(s) from being reallocated while they are copied. | 544 // the map(s) from being reallocated while they are copied. |
| 531 void SnapshotMaps(BirthMap* birth_map, | 545 void SnapshotMaps(BirthMap* birth_map, |
| 532 DeathMap* death_map, | 546 DeathMap* death_map, |
| 533 ParentChildSet* parent_child_set); | 547 ParentChildSet* parent_child_set); |
| 534 | 548 |
| 535 // This method is called by the TLS system when a thread terminates. | 549 // This method is called by the TLS system when a thread terminates. |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 ParentChildPairSnapshot(); | 753 ParentChildPairSnapshot(); |
| 740 explicit ParentChildPairSnapshot( | 754 explicit ParentChildPairSnapshot( |
| 741 const ThreadData::ParentChildPair& parent_child); | 755 const ThreadData::ParentChildPair& parent_child); |
| 742 ~ParentChildPairSnapshot(); | 756 ~ParentChildPairSnapshot(); |
| 743 | 757 |
| 744 BirthOnThreadSnapshot parent; | 758 BirthOnThreadSnapshot parent; |
| 745 BirthOnThreadSnapshot child; | 759 BirthOnThreadSnapshot child; |
| 746 }; | 760 }; |
| 747 | 761 |
| 748 //------------------------------------------------------------------------------ | 762 //------------------------------------------------------------------------------ |
| 749 // A snapshotted representation of the list of ThreadData objects for a process. | 763 // A snapshotted representation of the list of ThreadData objects for a process, |
| 764 // for a single profiling phase. |
| 765 |
| 766 struct BASE_EXPORT ProcessDataPhaseSnapshot { |
| 767 public: |
| 768 ProcessDataPhaseSnapshot(); |
| 769 ~ProcessDataPhaseSnapshot(); |
| 770 |
| 771 std::vector<TaskSnapshot> tasks; |
| 772 std::vector<ParentChildPairSnapshot> descendants; |
| 773 }; |
| 774 |
| 775 //------------------------------------------------------------------------------ |
| 776 // A snapshotted representation of the list of ThreadData objects for a process, |
| 777 // for all profiling phases, including the current one. |
| 750 | 778 |
| 751 struct BASE_EXPORT ProcessDataSnapshot { | 779 struct BASE_EXPORT ProcessDataSnapshot { |
| 752 public: | 780 public: |
| 753 ProcessDataSnapshot(); | 781 ProcessDataSnapshot(); |
| 754 ~ProcessDataSnapshot(); | 782 ~ProcessDataSnapshot(); |
| 755 | 783 |
| 756 std::vector<TaskSnapshot> tasks; | 784 PhasedProcessDataSnapshotMap phased_process_data_snapshots; |
| 757 std::vector<ParentChildPairSnapshot> descendants; | 785 base::ProcessId process_id; |
| 758 int process_id; | |
| 759 }; | 786 }; |
| 760 | 787 |
| 761 } // namespace tracked_objects | 788 } // namespace tracked_objects |
| 762 | 789 |
| 763 #endif // BASE_TRACKED_OBJECTS_H_ | 790 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |