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

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: More jar@ comments Created 6 years, 3 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 15 matching lines...) Expand all
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
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
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698