Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: base/tracked_objects.h

Issue 445413003: Creating a framework for suppressing pollution of the profiler data (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Adding 1 forgotten time parameter. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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,
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
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. Stopwatches
701 // coordinate with the stopwatches in which they are nested to avoid
702 // double-counting 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);
jar (doing other things) 2014/08/26 04:09:10 nit: I mentioned this elsewhere... Any reason why
vadimt 2014/08/26 19:15:05 See my answer in another comment.
711
712 // Starts stopwatch with the current time.
713 void Start() { Start(ThreadData::Now()); }
jar (doing other things) 2014/08/26 04:09:10 nit: You can't overload... but I suspect that only
vadimt 2014/08/26 19:15:04 Done.
714
715 // Stops stopwatch with the specified |start_time|.
jar (doing other things) 2014/08/26 04:09:09 nit: typo: start_time --> end_time
vadimt 2014/08/26 19:15:05 Done.
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.
jar (doing other things) 2014/08/26 04:09:09 nits: There is no real guarantee this is "wallcloc
vadimt 2014/08/26 19:15:05 Done, but I added a passage about being directly n
728 int32 RunDurationMs() const;
729
730 // Returns tracking info for the current thread.
731 ThreadData * GetThreadData() const;
jar (doing other things) 2014/08/26 04:09:09 nit: no space before the "*".
vadimt 2014/08/26 19:15:04 Done.
732
733 private:
734 // Time when the stopwatch was started.
735 TrackedTime start_time_;
736
737 // Wallclock duration of the task.
738 int32 wallclock_duration_ms_;
jar (doing other things) 2014/08/26 04:09:10 I don't see why this is stored, rather than being
vadimt 2014/08/26 19:15:04 Then I'd have to replace it with storing end_time,
739
740 // Tracking info for the current thread.
741 ThreadData* current_thread_data_;
742
743 // Total duration of all completed stopwatches that were directly nested in
744 // this one.
jar (doing other things) 2014/08/26 04:09:10 I expect you'll really need to sum (recursively) a
vadimt 2014/08/26 19:15:05 I believe summing only first-level nested stopwatc
745 int32 nested_stopwatches_duration_ms_;
jar (doing other things) 2014/08/26 04:09:10 nit: better name might be "excluded_duration_"
vadimt 2014/08/26 19:15:05 Done, but I added units to the name.
746
747 // Stopwatch which was running on our thread when this stopwatch was started.
748 // That preexisting stopwatch must be adjusted to the exclude the duration of
749 // of this stopwatch.
jar (doing other things) 2014/08/26 04:09:09 IMO, should be: ...exclude the duration the lifet
vadimt 2014/08/26 19:15:05 I added "of the lifetime". It's not clear what's
jar (doing other things) 2014/08/26 19:33:36 I meant "lifetime" to be time from construction to
vadimt 2014/08/26 19:47:45 OK. Since I believe that there are reasons to have
750 TaskStopwatch* parent_stopwatch_;
751
752 #ifndef NDEBUG
753 // State of the stopwatch. Stopwatch is reusable, i.e. it can be started after
754 // it was stopped.
755 enum {
756 CREATED,
757 RUNNING,
758 STOPPED
759 } state_;
760
761 // Currently running stopwatch that is directly nested in this one, if such
762 // stopwatch exists. NULL otherwise.
763 TaskStopwatch* running_child_;
jar (doing other things) 2014/08/26 04:09:09 nit: My preference would be to avoid putting test
vadimt 2014/08/26 19:15:04 This is not a test code. This is a code that helps
764 #endif
765 };
766
767 //------------------------------------------------------------------------------
693 // A snapshotted representation of a (parent, child) task pair, for tracking 768 // A snapshotted representation of a (parent, child) task pair, for tracking
694 // hierarchical profiles. 769 // hierarchical profiles.
695 770
696 struct BASE_EXPORT ParentChildPairSnapshot { 771 struct BASE_EXPORT ParentChildPairSnapshot {
697 public: 772 public:
698 ParentChildPairSnapshot(); 773 ParentChildPairSnapshot();
699 explicit ParentChildPairSnapshot( 774 explicit ParentChildPairSnapshot(
700 const ThreadData::ParentChildPair& parent_child); 775 const ThreadData::ParentChildPair& parent_child);
701 ~ParentChildPairSnapshot(); 776 ~ParentChildPairSnapshot();
702 777
(...skipping 10 matching lines...) Expand all
713 ~ProcessDataSnapshot(); 788 ~ProcessDataSnapshot();
714 789
715 std::vector<TaskSnapshot> tasks; 790 std::vector<TaskSnapshot> tasks;
716 std::vector<ParentChildPairSnapshot> descendants; 791 std::vector<ParentChildPairSnapshot> descendants;
717 int process_id; 792 int process_id;
718 }; 793 };
719 794
720 } // namespace tracked_objects 795 } // namespace tracked_objects
721 796
722 #endif // BASE_TRACKED_OBJECTS_H_ 797 #endif // BASE_TRACKED_OBJECTS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698