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 15 matching lines...) Expand all Loading... | |
453 static Status status(); | 452 static Status status(); |
454 | 453 |
455 // Indicate if any sort of profiling is being done (i.e., we are more than | 454 // Indicate if any sort of profiling is being done (i.e., we are more than |
456 // DEACTIVATED). | 455 // DEACTIVATED). |
457 static bool TrackingStatus(); | 456 static bool TrackingStatus(); |
458 | 457 |
459 // For testing only, indicate if the status of parent-child tracking is turned | 458 // For testing only, indicate if the status of parent-child tracking is turned |
460 // on. This is currently a compiled option, atop TrackingStatus(). | 459 // on. This is currently a compiled option, atop TrackingStatus(). |
461 static bool TrackingParentChildStatus(); | 460 static bool TrackingParentChildStatus(); |
462 | 461 |
463 // Special versions of Now() for getting times at start and end of a tracked | 462 // Marks a start of a tracked run. It's super fast when tracking is disabled, |
464 // run. They are super fast when tracking is disabled, and have some internal | 463 // and has some internal side effects when we are tracking, so that we can |
465 // side effects when we are tracking, so that we can deduce the amount of time | 464 // deduce the amount of time accumulated outside of execution of tracked runs. |
466 // accumulated outside of execution of tracked runs. | |
467 // The task that will be tracked is passed in as |parent| so that parent-child | 465 // The task that will be tracked is passed in as |parent| so that parent-child |
468 // relationships can be (optionally) calculated. | 466 // relationships can be (optionally) calculated. |
469 static TrackedTime NowForStartOfRun(const Births* parent); | 467 static void PrepareForStartOfRun(const Births* parent); |
470 static TrackedTime NowForEndOfRun(); | |
471 | 468 |
472 // Provide a time function that does nothing (runs fast) when we don't have | 469 // Provide a time function that does nothing (runs fast) when we don't have |
473 // the profiler enabled. It will generally be optimized away when it is | 470 // the profiler enabled. It will generally be optimized away when it is |
474 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of | 471 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of |
475 // the code). | 472 // the code). |
476 static TrackedTime Now(); | 473 static TrackedTime Now(); |
477 | 474 |
478 // Use the function |now| to provide current times, instead of calling the | 475 // Use the function |now| to provide current times, instead of calling the |
479 // TrackedTime::Now() function. Since this alternate function is being used, | 476 // TrackedTime::Now() function. Since this alternate function is being used, |
480 // the other time arguments (used for calculating queueing delay) will be | 477 // the other time arguments (used for calculating queueing delay) will be |
481 // ignored. | 478 // ignored. |
482 static void SetAlternateTimeSource(NowFunction* now); | 479 static void SetAlternateTimeSource(NowFunction* now); |
483 | 480 |
484 // This function can be called at process termination to validate that thread | 481 // 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 | 482 // cleanup routines have been called for at least some number of named |
486 // threads. | 483 // threads. |
487 static void EnsureCleanupWasCalled(int major_threads_shutdown_count); | 484 static void EnsureCleanupWasCalled(int major_threads_shutdown_count); |
488 | 485 |
489 private: | 486 private: |
487 friend class TaskStopwatch; | |
490 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it | 488 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it |
491 // in production code. | 489 // in production code. |
492 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a | 490 // 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 | 491 // better change of optimizing (inlining? etc.) private methods (knowing that |
494 // there will be no need for an external entry point). | 492 // there will be no need for an external entry point). |
495 friend class TrackedObjectsTest; | 493 friend class TrackedObjectsTest; |
496 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); | 494 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); |
497 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); | 495 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); |
498 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); | 496 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); |
499 | 497 |
(...skipping 16 matching lines...) Expand all Loading... | |
516 static ThreadData* first(); | 514 static ThreadData* first(); |
517 | 515 |
518 // Iterate through the null terminated list of ThreadData instances. | 516 // Iterate through the null terminated list of ThreadData instances. |
519 ThreadData* next() const; | 517 ThreadData* next() const; |
520 | 518 |
521 | 519 |
522 // In this thread's data, record a new birth. | 520 // In this thread's data, record a new birth. |
523 Births* TallyABirth(const Location& location); | 521 Births* TallyABirth(const Location& location); |
524 | 522 |
525 // Find a place to record a death on this thread. | 523 // Find a place to record a death on this thread. |
526 void TallyADeath(const Births& birth, int32 queue_duration, int32 duration); | 524 void TallyADeath(const Births& birth, |
525 int32 queue_duration, | |
526 const TaskStopwatch& stopwatch); | |
527 | 527 |
528 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData | 528 // 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 | 529 // 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 | 530 // 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 | 531 // true, then the max values in each DeathData instance are reset during the |
532 // scan. | 532 // scan. |
533 static void SnapshotAllExecutedTasks(bool reset_max, | 533 static void SnapshotAllExecutedTasks(bool reset_max, |
534 ProcessDataSnapshot* process_data, | 534 ProcessDataSnapshot* process_data, |
535 BirthCountMap* birth_counts); | 535 BirthCountMap* birth_counts); |
536 | 536 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 // threads since the time that InitializeAndSetTrackingStatus() was called, | 575 // threads since the time that InitializeAndSetTrackingStatus() was called, |
576 // then you can pass in a |leak| value of false, and this function will | 576 // then you can pass in a |leak| value of false, and this function will |
577 // delete recursively all data structures, starting with the list of | 577 // delete recursively all data structures, starting with the list of |
578 // ThreadData instances. | 578 // ThreadData instances. |
579 static void ShutdownSingleThreadedCleanup(bool leak); | 579 static void ShutdownSingleThreadedCleanup(bool leak); |
580 | 580 |
581 // When non-null, this specifies an external function that supplies monotone | 581 // When non-null, this specifies an external function that supplies monotone |
582 // increasing time functcion. | 582 // increasing time functcion. |
583 static NowFunction* now_function_; | 583 static NowFunction* now_function_; |
584 | 584 |
585 // If true, now_function_ returns values that can be used to calculate queue | |
586 // time. | |
587 static bool now_function_is_time_; | |
588 | |
585 // We use thread local store to identify which ThreadData to interact with. | 589 // We use thread local store to identify which ThreadData to interact with. |
586 static base::ThreadLocalStorage::StaticSlot tls_index_; | 590 static base::ThreadLocalStorage::StaticSlot tls_index_; |
587 | 591 |
588 // List of ThreadData instances for use with worker threads. When a worker | 592 // List of ThreadData instances for use with worker threads. When a worker |
589 // thread is done (terminated), we push it onto this llist. When a new worker | 593 // thread is done (terminated), we push it onto this llist. When a new worker |
590 // thread is created, we first try to re-use a ThreadData instance from the | 594 // thread is created, we first try to re-use a ThreadData instance from the |
591 // list, and if none are available, construct a new one. | 595 // list, and if none are available, construct a new one. |
592 // This is only accessed while list_lock_ is held. | 596 // This is only accessed while list_lock_ is held. |
593 static ThreadData* first_retired_worker_; | 597 static ThreadData* first_retired_worker_; |
594 | 598 |
(...skipping 84 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 | 683 // much randomness (because we can't call RandInt() on all our threads), so |
680 // we stir in more and more as we go. | 684 // we stir in more and more as we go. |
681 int32 random_number_; | 685 int32 random_number_; |
682 | 686 |
683 // Record of what the incarnation_counter_ was when this instance was created. | 687 // 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 | 688 // If the incarnation_counter_ has changed, then we avoid pushing into the |
685 // pool (this is only critical in tests which go through multiple | 689 // pool (this is only critical in tests which go through multiple |
686 // incarnations). | 690 // incarnations). |
687 int incarnation_count_for_pool_; | 691 int incarnation_count_for_pool_; |
688 | 692 |
693 // Most recently started (i.e. most nested) stopwatch on the current thread, | |
694 // if it exists; NULL otherwise. | |
695 TaskStopwatch* current_stopwatch_; | |
696 | |
689 DISALLOW_COPY_AND_ASSIGN(ThreadData); | 697 DISALLOW_COPY_AND_ASSIGN(ThreadData); |
690 }; | 698 }; |
691 | 699 |
692 //------------------------------------------------------------------------------ | 700 //------------------------------------------------------------------------------ |
701 // Stopwatch to measure task run time or simply create a time interval that will | |
702 // be subtracted from the current most nested task's run time. Stopwatches | |
703 // coordinate with the stopwatches in which they are nested to avoid | |
704 // double-counting nested tasks run times. | |
705 | |
706 class BASE_EXPORT TaskStopwatch { | |
707 public: | |
708 // Starts the stopwatch. | |
709 TaskStopwatch(); | |
710 ~TaskStopwatch(); | |
711 | |
712 // Stops stopwatch. | |
713 void Stop(); | |
714 | |
715 // Returns the start time. | |
716 TrackedTime StartTime() const; | |
717 | |
718 // Task's duration is calculated as the wallclock duration between starting | |
719 // and stopping this stopwatch, minus the wallclock durations of any other | |
720 // instances that are immediately nested in this one, started and stopped on | |
721 // this thread during that period. | |
722 int32 RunDurationMs() const; | |
723 | |
724 // Returns tracking info for the current thread. | |
725 ThreadData* GetThreadData() const; | |
726 | |
727 private: | |
728 // Time when the stopwatch was started. | |
729 TrackedTime start_time_; | |
730 | |
731 // Wallclock duration of the task. | |
732 int32 wallclock_duration_ms_; | |
733 | |
734 // Tracking info for the current thread. | |
735 ThreadData* current_thread_data_; | |
736 | |
737 // Sum of wallclock durations of all stopwatches that were directly nested in | |
738 // this one. | |
739 int32 excluded_duration_ms_; | |
740 | |
741 // Stopwatch which was running on our thread when this stopwatch was started. | |
742 // That preexisting stopwatch must be adjusted to the exclude the wallclock | |
743 // duration of this stopwatch. | |
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 RUNNING, | |
751 STOPPED | |
752 } state_; | |
753 | |
754 // Currently running stopwatch that is directly nested in this one, if such | |
755 // stopwatch exists. NULL otherwise. | |
756 TaskStopwatch* running_child_; | |
jar (doing other things)
2014/09/05 04:36:05
nit: Clean up names. This is really a backward li
vadimt
2014/09/05 20:25:55
Done.
| |
757 #endif | |
758 }; | |
759 | |
760 //------------------------------------------------------------------------------ | |
693 // A snapshotted representation of a (parent, child) task pair, for tracking | 761 // A snapshotted representation of a (parent, child) task pair, for tracking |
694 // hierarchical profiles. | 762 // hierarchical profiles. |
695 | 763 |
696 struct BASE_EXPORT ParentChildPairSnapshot { | 764 struct BASE_EXPORT ParentChildPairSnapshot { |
697 public: | 765 public: |
698 ParentChildPairSnapshot(); | 766 ParentChildPairSnapshot(); |
699 explicit ParentChildPairSnapshot( | 767 explicit ParentChildPairSnapshot( |
700 const ThreadData::ParentChildPair& parent_child); | 768 const ThreadData::ParentChildPair& parent_child); |
701 ~ParentChildPairSnapshot(); | 769 ~ParentChildPairSnapshot(); |
702 | 770 |
(...skipping 10 matching lines...) Expand all Loading... | |
713 ~ProcessDataSnapshot(); | 781 ~ProcessDataSnapshot(); |
714 | 782 |
715 std::vector<TaskSnapshot> tasks; | 783 std::vector<TaskSnapshot> tasks; |
716 std::vector<ParentChildPairSnapshot> descendants; | 784 std::vector<ParentChildPairSnapshot> descendants; |
717 int process_id; | 785 int process_id; |
718 }; | 786 }; |
719 | 787 |
720 } // namespace tracked_objects | 788 } // namespace tracked_objects |
721 | 789 |
722 #endif // BASE_TRACKED_OBJECTS_H_ | 790 #endif // BASE_TRACKED_OBJECTS_H_ |
OLD | NEW |