Chromium Code Reviews| 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 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 }; | 345 }; |
| 346 | 346 |
| 347 //------------------------------------------------------------------------------ | 347 //------------------------------------------------------------------------------ |
| 348 // For each thread, we have a ThreadData that stores all tracking info generated | 348 // For each thread, we have a ThreadData that stores all tracking info generated |
| 349 // on this thread. This prevents the need for locking as data accumulates. | 349 // on this thread. This prevents the need for locking as data accumulates. |
| 350 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. | 350 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. |
| 351 // We also have a linked list of ThreadData instances, and that list is used to | 351 // We also have a linked list of ThreadData instances, and that list is used to |
| 352 // harvest data from all existing instances. | 352 // harvest data from all existing instances. |
| 353 | 353 |
| 354 struct ProcessDataSnapshot; | 354 struct ProcessDataSnapshot; |
| 355 class BASE_EXPORT TaskStopwatch; | |
| 356 | |
| 355 class BASE_EXPORT ThreadData { | 357 class BASE_EXPORT ThreadData { |
| 356 public: | 358 public: |
| 357 // Current allowable states of the tracking system. The states can vary | 359 // Current allowable states of the tracking system. The states can vary |
| 358 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. | 360 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. |
| 359 enum Status { | 361 enum Status { |
| 360 UNINITIALIZED, // PRistine, link-time state before running. | 362 UNINITIALIZED, // PRistine, link-time state before running. |
| 361 DORMANT_DURING_TESTS, // Only used during testing. | 363 DORMANT_DURING_TESTS, // Only used during testing. |
| 362 DEACTIVATED, // No longer recording profling. | 364 DEACTIVATED, // No longer recording profling. |
| 363 PROFILING_ACTIVE, // Recording profiles (no parent-child links). | 365 PROFILING_ACTIVE, // Recording profiles (no parent-child links). |
| 364 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. | 366 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 // Records the end of a timed run of an object. The |completed_task| contains | 398 // Records the end of a timed run of an object. The |completed_task| contains |
| 397 // a pointer to a Births, the time_posted, and a delayed_start_time if any. | 399 // a pointer to a Births, the time_posted, and a delayed_start_time if any. |
| 398 // The |start_of_run| indicates when we started to perform the run of the | 400 // The |start_of_run| indicates when we started to perform the run of the |
| 399 // task. The delayed_start_time is non-null for tasks that were posted as | 401 // task. The delayed_start_time is non-null for tasks that were posted as |
| 400 // delayed tasks, and it indicates when the task should have run (i.e., when | 402 // delayed tasks, and it indicates when the task should have run (i.e., when |
| 401 // it should have posted out of the timer queue, and into the work queue. | 403 // it should have posted out of the timer queue, and into the work queue. |
| 402 // The |end_of_run| was just obtained by a call to Now() (just after the task | 404 // The |end_of_run| was just obtained by a call to Now() (just after the task |
| 403 // finished). It is provided as an argument to help with testing. | 405 // finished). It is provided as an argument to help with testing. |
| 404 static void TallyRunOnNamedThreadIfTracking( | 406 static void TallyRunOnNamedThreadIfTracking( |
| 405 const base::TrackingInfo& completed_task, | 407 const base::TrackingInfo& completed_task, |
| 406 const TrackedTime& start_of_run, | 408 const TaskStopwatch& stopwatch); |
| 407 const TrackedTime& end_of_run); | |
| 408 | 409 |
| 409 // Record the end of a timed run of an object. The |birth| is the record for | 410 // Record the end of a timed run of an object. The |birth| is the record for |
| 410 // the instance, the |time_posted| records that instant, which is presumed to | 411 // the instance, the |time_posted| records that instant, which is presumed to |
| 411 // be when the task was posted into a queue to run on a worker thread. | 412 // be when the task was posted into a queue to run on a worker thread. |
| 412 // The |start_of_run| is when the worker thread started to perform the run of | 413 // The |start_of_run| is when the worker thread started to perform the run of |
| 413 // the task. | 414 // the task. |
| 414 // The |end_of_run| was just obtained by a call to Now() (just after the task | 415 // The |end_of_run| was just obtained by a call to Now() (just after the task |
| 415 // finished). | 416 // finished). |
| 416 static void TallyRunOnWorkerThreadIfTracking( | 417 static void TallyRunOnWorkerThreadIfTracking( |
| 417 const Births* birth, | 418 const Births* birth, |
| 418 const TrackedTime& time_posted, | 419 const TrackedTime& time_posted, |
| 419 const TrackedTime& start_of_run, | 420 const TaskStopwatch& stopwatch); |
| 420 const TrackedTime& end_of_run); | |
| 421 | 421 |
| 422 // Record the end of execution in region, generally corresponding to a scope | 422 // Record the end of execution in region, generally corresponding to a scope |
| 423 // being exited. | 423 // being exited. |
| 424 static void TallyRunInAScopedRegionIfTracking( | 424 static void TallyRunInAScopedRegionIfTracking( |
| 425 const Births* birth, | 425 const Births* birth, |
| 426 const TrackedTime& start_of_run, | 426 const TaskStopwatch& stopwatch); |
| 427 const TrackedTime& end_of_run); | |
| 428 | 427 |
| 429 const std::string& thread_name() const { return thread_name_; } | 428 const std::string& thread_name() const { return thread_name_; } |
| 430 | 429 |
| 431 // Hack: asynchronously clear all birth counts and death tallies data values | 430 // Hack: asynchronously clear all birth counts and death tallies data values |
| 432 // in all ThreadData instances. The numerical (zeroing) part is done without | 431 // in all ThreadData instances. The numerical (zeroing) part is done without |
| 433 // use of a locks or atomics exchanges, and may (for int64 values) produce | 432 // use of a locks or atomics exchanges, and may (for int64 values) produce |
| 434 // bogus counts VERY rarely. | 433 // bogus counts VERY rarely. |
| 435 static void ResetAllThreadData(); | 434 static void ResetAllThreadData(); |
| 436 | 435 |
| 437 // Initializes all statics if needed (this initialization call should be made | 436 // Initializes all statics if needed (this initialization call should be made |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 // the other time arguments (used for calculating queueing delay) will be | 479 // the other time arguments (used for calculating queueing delay) will be |
| 481 // ignored. | 480 // ignored. |
| 482 static void SetAlternateTimeSource(NowFunction* now); | 481 static void SetAlternateTimeSource(NowFunction* now); |
| 483 | 482 |
| 484 // This function can be called at process termination to validate that thread | 483 // This function can be called at process termination to validate that thread |
| 485 // cleanup routines have been called for at least some number of named | 484 // cleanup routines have been called for at least some number of named |
| 486 // threads. | 485 // threads. |
| 487 static void EnsureCleanupWasCalled(int major_threads_shutdown_count); | 486 static void EnsureCleanupWasCalled(int major_threads_shutdown_count); |
| 488 | 487 |
| 489 private: | 488 private: |
| 489 friend class TaskStopwatch; | |
| 490 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it | 490 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it |
| 491 // in production code. | 491 // in production code. |
| 492 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a | 492 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a |
| 493 // better change of optimizing (inlining? etc.) private methods (knowing that | 493 // better change of optimizing (inlining? etc.) private methods (knowing that |
| 494 // there will be no need for an external entry point). | 494 // there will be no need for an external entry point). |
| 495 friend class TrackedObjectsTest; | 495 friend class TrackedObjectsTest; |
| 496 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); | 496 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); |
| 497 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); | 497 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); |
| 498 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); | 498 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); |
| 499 | 499 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 516 static ThreadData* first(); | 516 static ThreadData* first(); |
| 517 | 517 |
| 518 // Iterate through the null terminated list of ThreadData instances. | 518 // Iterate through the null terminated list of ThreadData instances. |
| 519 ThreadData* next() const; | 519 ThreadData* next() const; |
| 520 | 520 |
| 521 | 521 |
| 522 // In this thread's data, record a new birth. | 522 // In this thread's data, record a new birth. |
| 523 Births* TallyABirth(const Location& location); | 523 Births* TallyABirth(const Location& location); |
| 524 | 524 |
| 525 // Find a place to record a death on this thread. | 525 // Find a place to record a death on this thread. |
| 526 void TallyADeath(const Births& birth, int32 queue_duration, int32 duration); | 526 void TallyADeath(const Births& birth, |
|
jar (doing other things)
2014/08/08 01:34:48
Care was taken to use a 32 bit quantity. As I rec
vadimt
2014/08/08 20:39:34
TaskStopwatch still uses int32, so this is taken c
| |
| 527 int32 queue_duration, | |
| 528 const TaskStopwatch& stopwatch); | |
| 527 | 529 |
| 528 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData | 530 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData |
| 529 // instance. Also updates the |birth_counts| tally for each task to keep | 531 // instance. Also updates the |birth_counts| tally for each task to keep |
| 530 // track of the number of living instances of the task. If |reset_max| is | 532 // track of the number of living instances of the task. If |reset_max| is |
| 531 // true, then the max values in each DeathData instance are reset during the | 533 // true, then the max values in each DeathData instance are reset during the |
| 532 // scan. | 534 // scan. |
| 533 static void SnapshotAllExecutedTasks(bool reset_max, | 535 static void SnapshotAllExecutedTasks(bool reset_max, |
| 534 ProcessDataSnapshot* process_data, | 536 ProcessDataSnapshot* process_data, |
| 535 BirthCountMap* birth_counts); | 537 BirthCountMap* birth_counts); |
| 536 | 538 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 679 // much randomness (because we can't call RandInt() on all our threads), so | 681 // much randomness (because we can't call RandInt() on all our threads), so |
| 680 // we stir in more and more as we go. | 682 // we stir in more and more as we go. |
| 681 int32 random_number_; | 683 int32 random_number_; |
| 682 | 684 |
| 683 // Record of what the incarnation_counter_ was when this instance was created. | 685 // Record of what the incarnation_counter_ was when this instance was created. |
| 684 // If the incarnation_counter_ has changed, then we avoid pushing into the | 686 // If the incarnation_counter_ has changed, then we avoid pushing into the |
| 685 // pool (this is only critical in tests which go through multiple | 687 // pool (this is only critical in tests which go through multiple |
| 686 // incarnations). | 688 // incarnations). |
| 687 int incarnation_count_for_pool_; | 689 int incarnation_count_for_pool_; |
| 688 | 690 |
| 691 // Most recently started (i.e. most nested) stopwatch on the current thread, | |
| 692 // if it exists; NULL otherwise. | |
| 693 TaskStopwatch* current_stopwatch_; | |
| 694 | |
| 689 DISALLOW_COPY_AND_ASSIGN(ThreadData); | 695 DISALLOW_COPY_AND_ASSIGN(ThreadData); |
| 690 }; | 696 }; |
| 691 | 697 |
| 692 //------------------------------------------------------------------------------ | 698 //------------------------------------------------------------------------------ |
| 699 // Stopwatch to measure task run time or simply create a time interval that will | |
| 700 // be subtracted from the current most nested task's run time. Nested | |
| 701 // stopwatches coordinate with their parent stopwatches to avoid double-counting | |
| 702 // nested tasks run times. | |
| 703 | |
| 704 class BASE_EXPORT TaskStopwatch { | |
| 705 public: | |
| 706 TaskStopwatch(); | |
| 707 ~TaskStopwatch(); | |
| 708 | |
| 709 // Starts stopwatch with the specified |start_time|. | |
| 710 void Start(const TrackedTime& start_time); | |
| 711 | |
| 712 // Starts stopwatch with the current time. | |
| 713 void Start() { Start(ThreadData::Now()); } | |
| 714 | |
| 715 // Stops stopwatch with the specified |start_time|. | |
| 716 void Stop(const TrackedTime& end_time); | |
| 717 | |
| 718 // Stops stopwatch with the current time. | |
| 719 void Stop() { Stop(ThreadData::Now()); } | |
| 720 | |
| 721 // Returns the start time. | |
| 722 TrackedTime StartTime() const; | |
| 723 | |
| 724 // Returns task's duration. This method should be used when measuring run | |
| 725 // time for tasks. Task's durataion is calculated as the wallclock time | |
| 726 // difference between stopping the stopwatch and starting it, minus time | |
| 727 // spent in immediately nested stopwatches. | |
| 728 int32 TaskDurationMs() const; | |
| 729 | |
| 730 private: | |
| 731 // Time when the stopwatch was started. | |
| 732 TrackedTime start_time_; | |
| 733 | |
| 734 // Wallclock duration of the task. | |
| 735 int32 wallclock_duration_ms_; | |
| 736 | |
| 737 // Tracking info for the current thread. | |
| 738 ThreadData* current_thread_data_; | |
| 739 | |
| 740 // Total duration of all completed that were immediate children of this one. | |
| 741 int32 nested_stopwatches_duration_ms_; | |
| 742 | |
| 743 // Stopwatch of which this one is an immediate child. | |
|
jar (doing other things)
2014/08/08 01:34:48
The words "parent" and "child" seem confusing. I
vadimt
2014/08/08 20:39:34
Done.
| |
| 744 TaskStopwatch* parent_stopwatch_; | |
| 745 | |
| 746 #ifndef NDEBUG | |
| 747 // State of the stopwatch. Stopwatch is reusable, i.e. it can be started after | |
| 748 // it was stopped. | |
| 749 enum { | |
| 750 CREATED, | |
| 751 RUNNING, | |
| 752 STOPPED | |
| 753 } state_; | |
| 754 | |
| 755 // Currently running stopwatch that an immediate child of this one, if such | |
| 756 // child exists. NULL otherwise. | |
| 757 TaskStopwatch* running_child_; | |
| 758 #endif | |
| 759 }; | |
| 760 | |
| 761 //------------------------------------------------------------------------------ | |
| 693 // A snapshotted representation of a (parent, child) task pair, for tracking | 762 // A snapshotted representation of a (parent, child) task pair, for tracking |
| 694 // hierarchical profiles. | 763 // hierarchical profiles. |
| 695 | 764 |
| 696 struct BASE_EXPORT ParentChildPairSnapshot { | 765 struct BASE_EXPORT ParentChildPairSnapshot { |
| 697 public: | 766 public: |
| 698 ParentChildPairSnapshot(); | 767 ParentChildPairSnapshot(); |
| 699 explicit ParentChildPairSnapshot( | 768 explicit ParentChildPairSnapshot( |
| 700 const ThreadData::ParentChildPair& parent_child); | 769 const ThreadData::ParentChildPair& parent_child); |
| 701 ~ParentChildPairSnapshot(); | 770 ~ParentChildPairSnapshot(); |
| 702 | 771 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 713 ~ProcessDataSnapshot(); | 782 ~ProcessDataSnapshot(); |
| 714 | 783 |
| 715 std::vector<TaskSnapshot> tasks; | 784 std::vector<TaskSnapshot> tasks; |
| 716 std::vector<ParentChildPairSnapshot> descendants; | 785 std::vector<ParentChildPairSnapshot> descendants; |
| 717 int process_id; | 786 int process_id; |
| 718 }; | 787 }; |
| 719 | 788 |
| 720 } // namespace tracked_objects | 789 } // namespace tracked_objects |
| 721 | 790 |
| 722 #endif // BASE_TRACKED_OBJECTS_H_ | 791 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |