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

Side by Side Diff: base/tracked_objects.h

Issue 1104053004: Cleanup: removing unused descendants information from tracked objects (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: isherman@ comments Created 5 years, 7 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
« no previous file with comments | « base/threading/worker_pool_win.cc ('k') | base/tracked_objects.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // instances for each combination of birth thread, death thread, and location, 147 // instances for each combination of birth thread, death thread, and location,
148 // along with the count of such lifetimes. We gather such data into a 148 // along with the count of such lifetimes. We gather such data into a
149 // TaskSnapshot instances, so that such instances can be sorted and 149 // TaskSnapshot instances, so that such instances can be sorted and
150 // aggregated (and remain frozen during our processing). 150 // aggregated (and remain frozen during our processing).
151 // 151 //
152 // Profiling consists of phases. The concrete phase in the sequence of phases 152 // Profiling consists of phases. The concrete phase in the sequence of phases
153 // is identified by its 0-based index. 153 // is identified by its 0-based index.
154 // 154 //
155 // The ProcessDataPhaseSnapshot struct is a serialized representation of the 155 // The ProcessDataPhaseSnapshot struct is a serialized representation of the
156 // list of ThreadData objects for a process for a concrete profiling phase. It 156 // list of ThreadData objects for a process for a concrete profiling phase. It
157 // holds a set of TaskSnapshots and tracks parent/child relationships for the 157 // holds a set of TaskSnapshots. The statistics in a snapshot are gathered
158 // executed tasks. The statistics in a snapshot are gathered asynhcronously 158 // asynhcronously relative to their ongoing updates.
159 // relative to their ongoing updates.
160 // It is possible, though highly unlikely, that stats could be incorrectly 159 // It is possible, though highly unlikely, that stats could be incorrectly
161 // recorded by this process (all data is held in 32 bit ints, but we are not 160 // recorded by this process (all data is held in 32 bit ints, but we are not
162 // atomically collecting all data, so we could have count that does not, for 161 // atomically collecting all data, so we could have count that does not, for
163 // example, match with the number of durations we accumulated). The advantage 162 // example, match with the number of durations we accumulated). The advantage
164 // to having fast (non-atomic) updates of the data outweighs the minimal risk of 163 // to having fast (non-atomic) updates of the data outweighs the minimal risk of
165 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, 164 // a singular corrupt statistic snapshot (only the snapshot could be corrupt,
166 // not the underlying and ongoing statistic). In contrast, pointer data that 165 // not the underlying and ongoing statistic). In contrast, pointer data that
167 // is accessed during snapshotting is completely invariant, and hence is 166 // is accessed during snapshotting is completely invariant, and hence is
168 // perfectly acquired (i.e., no potential corruption, and no risk of a bad 167 // perfectly acquired (i.e., no potential corruption, and no risk of a bad
169 // memory reference). 168 // memory reference).
170 // 169 //
171 // TODO(jar): We can implement a Snapshot system that *tries* to grab the 170 // TODO(jar): We can implement a Snapshot system that *tries* to grab the
172 // snapshots on the source threads *when* they have MessageLoops available 171 // snapshots on the source threads *when* they have MessageLoops available
173 // (worker threads don't have message loops generally, and hence gathering from 172 // (worker threads don't have message loops generally, and hence gathering from
174 // them will continue to be asynchronous). We had an implementation of this in 173 // them will continue to be asynchronous). We had an implementation of this in
175 // the past, but the difficulty is dealing with message loops being terminated. 174 // the past, but the difficulty is dealing with message loops being terminated.
176 // We can *try* to spam the available threads via some message loop proxy to 175 // We can *try* to spam the available threads via some message loop proxy to
177 // achieve this feat, and it *might* be valuable when we are collecting data 176 // achieve this feat, and it *might* be valuable when we are collecting data
178 // for upload via UMA (where correctness of data may be more significant than 177 // for upload via UMA (where correctness of data may be more significant than
179 // for a single screen of about:profiler). 178 // for a single screen of about:profiler).
180 // 179 //
181 // TODO(jar): We should support (optionally) the recording of parent-child
182 // relationships for tasks. This should be done by detecting what tasks are
183 // Born during the running of a parent task. The resulting data can be used by
184 // a smarter profiler to aggregate the cost of a series of child tasks into
185 // the ancestor task. It can also be used to illuminate what child or parent is
186 // related to each task.
187 //
188 // TODO(jar): We need to store DataCollections, and provide facilities for 180 // TODO(jar): We need to store DataCollections, and provide facilities for
189 // taking the difference between two gathered DataCollections. For now, we're 181 // taking the difference between two gathered DataCollections. For now, we're
190 // just adding a hack that Reset()s to zero all counts and stats. This is also 182 // just adding a hack that Reset()s to zero all counts and stats. This is also
191 // done in a slightly thread-unsafe fashion, as the resetting is done 183 // done in a slightly thread-unsafe fashion, as the resetting is done
192 // asynchronously relative to ongoing updates (but all data is 32 bit in size). 184 // asynchronously relative to ongoing updates (but all data is 32 bit in size).
193 // For basic profiling, this will work "most of the time," and should be 185 // For basic profiling, this will work "most of the time," and should be
194 // sufficient... but storing away DataCollections is the "right way" to do this. 186 // sufficient... but storing away DataCollections is the "right way" to do this.
195 // We'll accomplish this via JavaScript storage of snapshots, and then we'll 187 // We'll accomplish this via JavaScript storage of snapshots, and then we'll
196 // remove the Reset() methods. We may also need a short-term-max value in 188 // remove the Reset() methods. We may also need a short-term-max value in
197 // DeathData that is reset (as synchronously as possible) during each snapshot. 189 // DeathData that is reset (as synchronously as possible) during each snapshot.
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 // Map from profiling phase number to the process-wide snapshotted 415 // Map from profiling phase number to the process-wide snapshotted
424 // representation of the list of ThreadData objects that died during the given 416 // representation of the list of ThreadData objects that died during the given
425 // phase. 417 // phase.
426 typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshotMap; 418 typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshotMap;
427 419
428 class BASE_EXPORT ThreadData { 420 class BASE_EXPORT ThreadData {
429 public: 421 public:
430 // Current allowable states of the tracking system. The states can vary 422 // Current allowable states of the tracking system. The states can vary
431 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. 423 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED.
432 enum Status { 424 enum Status {
433 UNINITIALIZED, // PRistine, link-time state before running. 425 UNINITIALIZED, // Pristine, link-time state before running.
434 DORMANT_DURING_TESTS, // Only used during testing. 426 DORMANT_DURING_TESTS, // Only used during testing.
435 DEACTIVATED, // No longer recording profiling. 427 DEACTIVATED, // No longer recording profiling.
436 PROFILING_ACTIVE, // Recording profiles (no parent-child links). 428 PROFILING_ACTIVE, // Recording profiles.
437 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. 429 STATUS_LAST = PROFILING_ACTIVE
438 STATUS_LAST = PROFILING_CHILDREN_ACTIVE
439 }; 430 };
440 431
441 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; 432 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap;
442 typedef std::map<const Births*, DeathData> DeathMap; 433 typedef std::map<const Births*, DeathData> DeathMap;
443 typedef std::pair<const Births*, const Births*> ParentChildPair;
444 typedef std::set<ParentChildPair> ParentChildSet;
445 typedef std::stack<const Births*> ParentStack;
446 434
447 // Initialize the current thread context with a new instance of ThreadData. 435 // Initialize the current thread context with a new instance of ThreadData.
448 // This is used by all threads that have names, and should be explicitly 436 // This is used by all threads that have names, and should be explicitly
449 // set *before* any births on the threads have taken place. It is generally 437 // set *before* any births on the threads have taken place. It is generally
450 // only used by the message loop, which has a well defined thread name. 438 // only used by the message loop, which has a well defined thread name.
451 static void InitializeThreadContext(const std::string& suggested_name); 439 static void InitializeThreadContext(const std::string& suggested_name);
452 440
453 // Using Thread Local Store, find the current instance for collecting data. 441 // Using Thread Local Store, find the current instance for collecting data.
454 // If an instance does not exist, construct one (and remember it for use on 442 // If an instance does not exist, construct one (and remember it for use on
455 // this thread. 443 // this thread.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 const TaskStopwatch& stopwatch); 495 const TaskStopwatch& stopwatch);
508 496
509 const std::string& thread_name() const { return thread_name_; } 497 const std::string& thread_name() const { return thread_name_; }
510 498
511 // Initializes all statics if needed (this initialization call should be made 499 // Initializes all statics if needed (this initialization call should be made
512 // while we are single threaded). Returns false if unable to initialize. 500 // while we are single threaded). Returns false if unable to initialize.
513 static bool Initialize(); 501 static bool Initialize();
514 502
515 // Sets internal status_. 503 // Sets internal status_.
516 // If |status| is false, then status_ is set to DEACTIVATED. 504 // If |status| is false, then status_ is set to DEACTIVATED.
517 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or 505 // If |status| is true, then status_ is set to PROFILING_ACTIVE.
518 // PROFILING_CHILDREN_ACTIVE. 506 // If it fails to initialize the TLS slot, this function will return false.
519 // If tracking is not compiled in, this function will return false.
520 // If parent-child tracking is not compiled in, then an attempt to set the
521 // status to PROFILING_CHILDREN_ACTIVE will only result in a status of
522 // PROFILING_ACTIVE (i.e., it can't be set to a higher level than what is
523 // compiled into the binary, and parent-child tracking at the
524 // PROFILING_CHILDREN_ACTIVE level might not be compiled in).
525 static bool InitializeAndSetTrackingStatus(Status status); 507 static bool InitializeAndSetTrackingStatus(Status status);
526 508
527 static Status status(); 509 static Status status();
528 510
529 // Indicate if any sort of profiling is being done (i.e., we are more than 511 // Indicate if any sort of profiling is being done (i.e., we are more than
530 // DEACTIVATED). 512 // DEACTIVATED).
531 static bool TrackingStatus(); 513 static bool TrackingStatus();
532 514
533 // For testing only, indicate if the status of parent-child tracking is turned
534 // on. This is currently a compiled option, atop TrackingStatus().
535 static bool TrackingParentChildStatus();
536
537 // Marks a start of a tracked run. It's super fast when tracking is disabled,
538 // and has some internal side effects when we are tracking, so that we can
539 // deduce the amount of time accumulated outside of execution of tracked runs.
540 // The task that will be tracked is passed in as |parent| so that parent-child
541 // relationships can be (optionally) calculated.
542 static void PrepareForStartOfRun(const Births* parent);
543
544 // Enables profiler timing. 515 // Enables profiler timing.
545 static void EnableProfilerTiming(); 516 static void EnableProfilerTiming();
546 517
547 // Provide a time function that does nothing (runs fast) when we don't have 518 // Provide a time function that does nothing (runs fast) when we don't have
548 // the profiler enabled. It will generally be optimized away when it is 519 // the profiler enabled. It will generally be optimized away when it is
549 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of 520 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of
550 // the code). 521 // the code).
551 static TrackedTime Now(); 522 static TrackedTime Now();
552 523
553 // Use the function |now| to provide current times, instead of calling the 524 // Use the function |now| to provide current times, instead of calling the
(...skipping 10 matching lines...) Expand all
564 private: 535 private:
565 friend class TaskStopwatch; 536 friend class TaskStopwatch;
566 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it 537 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it
567 // in production code. 538 // in production code.
568 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a 539 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a
569 // better change of optimizing (inlining? etc.) private methods (knowing that 540 // better change of optimizing (inlining? etc.) private methods (knowing that
570 // there will be no need for an external entry point). 541 // there will be no need for an external entry point).
571 friend class TrackedObjectsTest; 542 friend class TrackedObjectsTest;
572 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); 543 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown);
573 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); 544 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown);
574 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest);
575 545
576 typedef std::map<const BirthOnThread*, int> BirthCountMap; 546 typedef std::map<const BirthOnThread*, int> BirthCountMap;
577 547
578 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> 548 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>>
579 DeathsSnapshot; 549 DeathsSnapshot;
580 550
581 // Worker thread construction creates a name since there is none. 551 // Worker thread construction creates a name since there is none.
582 explicit ThreadData(int thread_number); 552 explicit ThreadData(int thread_number);
583 553
584 // Message loop based construction should provide a name. 554 // Message loop based construction should provide a name.
(...skipping 30 matching lines...) Expand all
615 // number of births for the task that have not yet been balanced by a death. 585 // number of births for the task that have not yet been balanced by a death.
616 void SnapshotExecutedTasks(int current_profiling_phase, 586 void SnapshotExecutedTasks(int current_profiling_phase,
617 PhasedProcessDataSnapshotMap* phased_snapshots, 587 PhasedProcessDataSnapshotMap* phased_snapshots,
618 BirthCountMap* birth_counts); 588 BirthCountMap* birth_counts);
619 589
620 // Using our lock, make a copy of the specified maps. This call may be made 590 // Using our lock, make a copy of the specified maps. This call may be made
621 // on non-local threads, which necessitate the use of the lock to prevent 591 // on non-local threads, which necessitate the use of the lock to prevent
622 // the map(s) from being reallocated while they are copied. 592 // the map(s) from being reallocated while they are copied.
623 void SnapshotMaps(int profiling_phase, 593 void SnapshotMaps(int profiling_phase,
624 BirthMap* birth_map, 594 BirthMap* birth_map,
625 DeathsSnapshot* deaths, 595 DeathsSnapshot* deaths);
626 ParentChildSet* parent_child_set);
627 596
628 // Called for this thread when the current profiling phase, identified by 597 // Called for this thread when the current profiling phase, identified by
629 // |profiling_phase|, ends. 598 // |profiling_phase|, ends.
630 void OnProfilingPhaseCompletedOnThread(int profiling_phase); 599 void OnProfilingPhaseCompletedOnThread(int profiling_phase);
631 600
632 // This method is called by the TLS system when a thread terminates. 601 // This method is called by the TLS system when a thread terminates.
633 // The argument may be NULL if this thread has never tracked a birth or death. 602 // The argument may be NULL if this thread has never tracked a birth or death.
634 static void OnThreadTermination(void* thread_data); 603 static void OnThreadTermination(void* thread_data);
635 604
636 // This method should be called when a worker thread terminates, so that we 605 // This method should be called when a worker thread terminates, so that we
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 // When a snapshot is needed, this structure can be locked in place for the 687 // When a snapshot is needed, this structure can be locked in place for the
719 // duration of the snapshotting activity. 688 // duration of the snapshotting activity.
720 BirthMap birth_map_; 689 BirthMap birth_map_;
721 690
722 // Similar to birth_map_, this records informations about death of tracked 691 // Similar to birth_map_, this records informations about death of tracked
723 // instances (i.e., when a tracked instance was destroyed on this thread). 692 // instances (i.e., when a tracked instance was destroyed on this thread).
724 // It is locked before changing, and hence other threads may access it by 693 // It is locked before changing, and hence other threads may access it by
725 // locking before reading it. 694 // locking before reading it.
726 DeathMap death_map_; 695 DeathMap death_map_;
727 696
728 // A set of parents that created children tasks on this thread. Each pair
729 // corresponds to potentially non-local Births (location and thread), and a
730 // local Births (that took place on this thread).
731 ParentChildSet parent_child_set_;
732
733 // Lock to protect *some* access to BirthMap and DeathMap. The maps are 697 // Lock to protect *some* access to BirthMap and DeathMap. The maps are
734 // regularly read and written on this thread, but may only be read from other 698 // regularly read and written on this thread, but may only be read from other
735 // threads. To support this, we acquire this lock if we are writing from this 699 // threads. To support this, we acquire this lock if we are writing from this
736 // thread, or reading from another thread. For reading from this thread we 700 // thread, or reading from another thread. For reading from this thread we
737 // don't need a lock, as there is no potential for a conflict since the 701 // don't need a lock, as there is no potential for a conflict since the
738 // writing is only done from this thread. 702 // writing is only done from this thread.
739 mutable base::Lock map_lock_; 703 mutable base::Lock map_lock_;
740 704
741 // The stack of parents that are currently being profiled. This includes only
742 // tasks that have started a timer recently via PrepareForStartOfRun(), but
743 // not yet concluded with a NowForEndOfRun(). Usually this stack is one deep,
744 // but if a scoped region is profiled, or <sigh> a task runs a nested-message
745 // loop, then the stack can grow larger. Note that we don't try to deduct
746 // time in nested profiles, as our current timer is based on wall-clock time,
747 // and not CPU time (and we're hopeful that nested timing won't be a
748 // significant additional cost).
749 ParentStack parent_stack_;
750
751 // A random number that we used to select decide which sample to keep as a 705 // A random number that we used to select decide which sample to keep as a
752 // representative sample in each DeathData instance. We can't start off with 706 // representative sample in each DeathData instance. We can't start off with
753 // much randomness (because we can't call RandInt() on all our threads), so 707 // much randomness (because we can't call RandInt() on all our threads), so
754 // we stir in more and more as we go. 708 // we stir in more and more as we go.
755 uint32 random_number_; 709 uint32 random_number_;
756 710
757 // Record of what the incarnation_counter_ was when this instance was created. 711 // Record of what the incarnation_counter_ was when this instance was created.
758 // If the incarnation_counter_ has changed, then we avoid pushing into the 712 // If the incarnation_counter_ has changed, then we avoid pushing into the
759 // pool (this is only critical in tests which go through multiple 713 // pool (this is only critical in tests which go through multiple
760 // incarnations). 714 // incarnations).
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 // state, then is optionally started/stopped, then destructed. 775 // state, then is optionally started/stopped, then destructed.
822 enum { CREATED, RUNNING, STOPPED } state_; 776 enum { CREATED, RUNNING, STOPPED } state_;
823 777
824 // Currently running stopwatch that is directly nested in this one, if such 778 // Currently running stopwatch that is directly nested in this one, if such
825 // stopwatch exists. NULL otherwise. 779 // stopwatch exists. NULL otherwise.
826 TaskStopwatch* child_; 780 TaskStopwatch* child_;
827 #endif 781 #endif
828 }; 782 };
829 783
830 //------------------------------------------------------------------------------ 784 //------------------------------------------------------------------------------
831 // A snapshotted representation of a (parent, child) task pair, for tracking
832 // hierarchical profiles.
833
834 struct BASE_EXPORT ParentChildPairSnapshot {
835 public:
836 ParentChildPairSnapshot();
837 explicit ParentChildPairSnapshot(
838 const ThreadData::ParentChildPair& parent_child);
839 ~ParentChildPairSnapshot();
840
841 BirthOnThreadSnapshot parent;
842 BirthOnThreadSnapshot child;
843 };
844
845 //------------------------------------------------------------------------------
846 // A snapshotted representation of the list of ThreadData objects for a process, 785 // A snapshotted representation of the list of ThreadData objects for a process,
847 // for a single profiling phase. 786 // for a single profiling phase.
848 787
849 struct BASE_EXPORT ProcessDataPhaseSnapshot { 788 struct BASE_EXPORT ProcessDataPhaseSnapshot {
850 public: 789 public:
851 ProcessDataPhaseSnapshot(); 790 ProcessDataPhaseSnapshot();
852 ~ProcessDataPhaseSnapshot(); 791 ~ProcessDataPhaseSnapshot();
853 792
854 std::vector<TaskSnapshot> tasks; 793 std::vector<TaskSnapshot> tasks;
855 std::vector<ParentChildPairSnapshot> descendants;
856 }; 794 };
857 795
858 //------------------------------------------------------------------------------ 796 //------------------------------------------------------------------------------
859 // A snapshotted representation of the list of ThreadData objects for a process, 797 // A snapshotted representation of the list of ThreadData objects for a process,
860 // for all profiling phases, including the current one. 798 // for all profiling phases, including the current one.
861 799
862 struct BASE_EXPORT ProcessDataSnapshot { 800 struct BASE_EXPORT ProcessDataSnapshot {
863 public: 801 public:
864 ProcessDataSnapshot(); 802 ProcessDataSnapshot();
865 ~ProcessDataSnapshot(); 803 ~ProcessDataSnapshot();
866 804
867 PhasedProcessDataSnapshotMap phased_snapshots; 805 PhasedProcessDataSnapshotMap phased_snapshots;
868 base::ProcessId process_id; 806 base::ProcessId process_id;
869 }; 807 };
870 808
871 } // namespace tracked_objects 809 } // namespace tracked_objects
872 810
873 #endif // BASE_TRACKED_OBJECTS_H_ 811 #endif // BASE_TRACKED_OBJECTS_H_
OLDNEW
« no previous file with comments | « base/threading/worker_pool_win.cc ('k') | base/tracked_objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698