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 |