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

Side by Side Diff: base/tracked_objects.h

Issue 985773002: Introducing phased profiling framework (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@write_to_file
Patch Set: Only "API" Created 5 years, 9 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 | « no previous file | base/tracked_objects.cc » ('j') | base/tracked_objects.cc » ('J')
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 // (3) the snapshotted data. 139 // (3) the snapshotted data.
140 // 140 //
141 // For a given birth location, information about births is spread across data 141 // For a given birth location, information about births is spread across data
142 // structures that are asynchronously changing on various threads. For 142 // structures that are asynchronously changing on various threads. For
143 // serialization and display purposes, we need to construct TaskSnapshot 143 // serialization and display purposes, we need to construct TaskSnapshot
144 // instances for each combination of birth thread, death thread, and location, 144 // instances for each combination of birth thread, death thread, and location,
145 // along with the count of such lifetimes. We gather such data into a 145 // along with the count of such lifetimes. We gather such data into a
146 // TaskSnapshot instances, so that such instances can be sorted and 146 // TaskSnapshot instances, so that such instances can be sorted and
147 // aggregated (and remain frozen during our processing). 147 // aggregated (and remain frozen during our processing).
148 // 148 //
149 // The ProcessDataSnapshot struct is a serialized representation of the list 149 // Profiling consists of phases. The concrete phase in the sequence of phases is
150 // of ThreadData objects for a process. It holds a set of TaskSnapshots 150 // identified by its 0-based nubmer.
Ilya Sherman 2015/03/10 00:48:10 nit: "0-based" -> "0-index"; "number" -> "id numbe
vadimt 2015/03/13 23:18:01 Done; the new terminology looks the most common.
151 // and tracks parent/child relationships for the executed tasks. The statistics 151 //
152 // in a snapshot are gathered asynhcronously relative to their ongoing updates. 152 // The ProcessDataPhaseSnapshot struct is a serialized representation of the
153 // list of ThreadData objects for a process for a concrete profiling phase. It
154 // holds a set of TaskSnapshots and tracks parent/child relationships for the
155 // executed tasks. The statistics in a snapshot are gathered asynhcronously
156 // relative to their ongoing updates.
153 // It is possible, though highly unlikely, that stats could be incorrectly 157 // It is possible, though highly unlikely, that stats could be incorrectly
154 // recorded by this process (all data is held in 32 bit ints, but we are not 158 // recorded by this process (all data is held in 32 bit ints, but we are not
155 // atomically collecting all data, so we could have count that does not, for 159 // atomically collecting all data, so we could have count that does not, for
156 // example, match with the number of durations we accumulated). The advantage 160 // example, match with the number of durations we accumulated). The advantage
157 // to having fast (non-atomic) updates of the data outweighs the minimal risk of 161 // to having fast (non-atomic) updates of the data outweighs the minimal risk of
158 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, 162 // a singular corrupt statistic snapshot (only the snapshot could be corrupt,
159 // not the underlying and ongoing statistic). In contrast, pointer data that 163 // not the underlying and ongoing statistic). In contrast, pointer data that
160 // is accessed during snapshotting is completely invariant, and hence is 164 // is accessed during snapshotting is completely invariant, and hence is
161 // perfectly acquired (i.e., no potential corruption, and no risk of a bad 165 // perfectly acquired (i.e., no potential corruption, and no risk of a bad
162 // memory reference). 166 // memory reference).
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 std::string death_thread_name; 338 std::string death_thread_name;
335 }; 339 };
336 340
337 //------------------------------------------------------------------------------ 341 //------------------------------------------------------------------------------
338 // For each thread, we have a ThreadData that stores all tracking info generated 342 // For each thread, we have a ThreadData that stores all tracking info generated
339 // on this thread. This prevents the need for locking as data accumulates. 343 // on this thread. This prevents the need for locking as data accumulates.
340 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. 344 // We use ThreadLocalStorage to quickly identfy the current ThreadData context.
341 // We also have a linked list of ThreadData instances, and that list is used to 345 // We also have a linked list of ThreadData instances, and that list is used to
342 // harvest data from all existing instances. 346 // harvest data from all existing instances.
343 347
348 struct ProcessDataPhaseSnapshot;
349 // Map from profiling phase number to the process-wide snapshotted
350 // representation of the list of ThreadData objects that died during the given
351 // phase.
352 typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshots;
Ilya Sherman 2015/03/10 00:48:10 As elsewhere, I'd prefer that you not use a typede
vadimt 2015/03/13 23:18:01 Done. A process may start after several phase chan
Ilya Sherman 2015/03/14 00:20:34 I guess I was thinking that the phase number -- or
vadimt 2015/03/14 01:39:15 The event type is declared outside of base, and we
Ilya Sherman 2015/03/17 23:57:38 Fair enough.
vadimt 2015/03/19 00:20:44 I'm using phase number to quickly find the entry i
Ilya Sherman 2015/03/19 01:00:51 I'm pretty unconvinced by this explanation -- it's
344 struct ProcessDataSnapshot; 353 struct ProcessDataSnapshot;
345 class BASE_EXPORT TaskStopwatch; 354 class BASE_EXPORT TaskStopwatch;
346 355
347 class BASE_EXPORT ThreadData { 356 class BASE_EXPORT ThreadData {
348 public: 357 public:
349 // Current allowable states of the tracking system. The states can vary 358 // Current allowable states of the tracking system. The states can vary
350 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. 359 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED.
351 enum Status { 360 enum Status {
352 UNINITIALIZED, // PRistine, link-time state before running. 361 UNINITIALIZED, // PRistine, link-time state before running.
353 DORMANT_DURING_TESTS, // Only used during testing. 362 DORMANT_DURING_TESTS, // Only used during testing.
(...skipping 14 matching lines...) Expand all
368 // set *before* any births on the threads have taken place. It is generally 377 // set *before* any births on the threads have taken place. It is generally
369 // only used by the message loop, which has a well defined thread name. 378 // only used by the message loop, which has a well defined thread name.
370 static void InitializeThreadContext(const std::string& suggested_name); 379 static void InitializeThreadContext(const std::string& suggested_name);
371 380
372 // Using Thread Local Store, find the current instance for collecting data. 381 // Using Thread Local Store, find the current instance for collecting data.
373 // If an instance does not exist, construct one (and remember it for use on 382 // If an instance does not exist, construct one (and remember it for use on
374 // this thread. 383 // this thread.
375 // This may return NULL if the system is disabled for any reason. 384 // This may return NULL if the system is disabled for any reason.
376 static ThreadData* Get(); 385 static ThreadData* Get();
377 386
378 // Fills |process_data| with all the recursive results in our process. 387 // Fills |process_data_snapshot| with phased snapshots of all profiling
379 static void Snapshot(ProcessDataSnapshot* process_data); 388 // phases, including the current one.
389 static void GetProcessDataSnapshot(
390 ProcessDataSnapshot* process_data_snapshot);
380 391
381 // Finds (or creates) a place to count births from the given location in this 392 // Finds (or creates) a place to count births from the given location in this
382 // thread, and increment that tally. 393 // thread, and increment that tally.
383 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. 394 // TallyABirthIfActive will returns NULL if the birth cannot be tallied.
384 static Births* TallyABirthIfActive(const Location& location); 395 static Births* TallyABirthIfActive(const Location& location);
385 396
386 // Records the end of a timed run of an object. The |completed_task| contains 397 // Records the end of a timed run of an object. The |completed_task| contains
387 // a pointer to a Births, the time_posted, and a delayed_start_time if any. 398 // a pointer to a Births, the time_posted, and a delayed_start_time if any.
388 // The |start_of_run| indicates when we started to perform the run of the 399 // The |start_of_run| indicates when we started to perform the run of the
389 // task. The delayed_start_time is non-null for tasks that were posted as 400 // task. The delayed_start_time is non-null for tasks that were posted as
390 // delayed tasks, and it indicates when the task should have run (i.e., when 401 // delayed tasks, and it indicates when the task should have run (i.e., when
391 // it should have posted out of the timer queue, and into the work queue. 402 // it should have posted out of the timer queue, and into the work queue.
392 // The |end_of_run| was just obtained by a call to Now() (just after the task 403 // The |end_of_run| was just obtained by a call to Now() (just after the task
393 // finished). It is provided as an argument to help with testing. 404 // finished). It is provided as an argument to help with testing.
394 static void TallyRunOnNamedThreadIfTracking( 405 static void TallyRunOnNamedThreadIfTracking(
395 const base::TrackingInfo& completed_task, 406 const base::TrackingInfo& completed_task,
396 const TaskStopwatch& stopwatch); 407 const TaskStopwatch& stopwatch);
397 408
398 // Record the end of a timed run of an object. The |birth| is the record for 409 // Record the end of a timed run of an object. The |birth| is the record for
399 // the instance, the |time_posted| records that instant, which is presumed to 410 // the instance, the |time_posted| records that instant, which is presumed to
400 // be when the task was posted into a queue to run on a worker thread. 411 // be when the task was posted into a queue to run on a worker thread.
401 // The |start_of_run| is when the worker thread started to perform the run of 412 // The |start_of_run| is when the worker thread started to perform the run of
402 // the task. 413 // the task.
403 // The |end_of_run| was just obtained by a call to Now() (just after the task 414 // The |end_of_run| was just obtained by a call to Now() (just after the task
404 // finished). 415 // finished).
405 static void TallyRunOnWorkerThreadIfTracking( 416 static void TallyRunOnWorkerThreadIfTracking(const Births* birth,
406 const Births* birth, 417 const TrackedTime& time_posted,
407 const TrackedTime& time_posted, 418 const TaskStopwatch& stopwatch);
408 const TaskStopwatch& stopwatch);
409 419
410 // Record the end of execution in region, generally corresponding to a scope 420 // Record the end of execution in region, generally corresponding to a scope
411 // being exited. 421 // being exited.
412 static void TallyRunInAScopedRegionIfTracking( 422 static void TallyRunInAScopedRegionIfTracking(const Births* birth,
413 const Births* birth, 423 const TaskStopwatch& stopwatch);
Ilya Sherman 2015/03/10 00:48:10 nit: Are these two blocks just unrelated formattin
vadimt 2015/03/13 23:18:01 I'm using git cl format, which wants to format thi
414 const TaskStopwatch& stopwatch);
415 424
416 const std::string& thread_name() const { return thread_name_; } 425 const std::string& thread_name() const { return thread_name_; }
417 426
418 // Initializes all statics if needed (this initialization call should be made 427 // Initializes all statics if needed (this initialization call should be made
419 // while we are single threaded). Returns false if unable to initialize. 428 // while we are single threaded). Returns false if unable to initialize.
420 static bool Initialize(); 429 static bool Initialize();
421 430
422 // Sets internal status_. 431 // Sets internal status_.
423 // If |status| is false, then status_ is set to DEACTIVATED. 432 // If |status| is false, then status_ is set to DEACTIVATED.
424 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or 433 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 Births* TallyABirth(const Location& location); 515 Births* TallyABirth(const Location& location);
507 516
508 // Find a place to record a death on this thread. 517 // Find a place to record a death on this thread.
509 void TallyADeath(const Births& birth, 518 void TallyADeath(const Births& birth,
510 int32 queue_duration, 519 int32 queue_duration,
511 const TaskStopwatch& stopwatch); 520 const TaskStopwatch& stopwatch);
512 521
513 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData 522 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData
514 // instance. Also updates the |birth_counts| tally for each task to keep 523 // instance. Also updates the |birth_counts| tally for each task to keep
515 // track of the number of living instances of the task. 524 // track of the number of living instances of the task.
516 static void SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data, 525 static void SnapshotAllExecutedTasks(
517 BirthCountMap* birth_counts); 526 ProcessDataPhaseSnapshot* process_data_phase,
527 BirthCountMap* birth_counts);
528
529 // Fills |process_data_phase| with all the recursive results in our process.
530 static void Snapshot(ProcessDataPhaseSnapshot* process_data_phase);
518 531
519 // Snapshots (under a lock) the profiled data for the tasks for this thread 532 // Snapshots (under a lock) the profiled data for the tasks for this thread
520 // and writes all of the executed tasks' data -- i.e. the data for the tasks 533 // and writes all of the executed tasks' data -- i.e. the data for the tasks
521 // with with entries in the death_map_ -- into |process_data|. Also updates 534 // with with entries in the death_map_ -- into |process_data_phase|. Also
522 // the |birth_counts| tally for each task to keep track of the number of 535 // updates the |birth_counts| tally for each task to keep track of the number
523 // living instances of the task -- that is, each task maps to the number of 536 // of living instances of the task -- that is, each task maps to the number of
524 // births for the task that have not yet been balanced by a death. 537 // births for the task that have not yet been balanced by a death.
525 void SnapshotExecutedTasks(ProcessDataSnapshot* process_data, 538 void SnapshotExecutedTasks(ProcessDataPhaseSnapshot* process_data_phase,
526 BirthCountMap* birth_counts); 539 BirthCountMap* birth_counts);
527 540
528 // Using our lock, make a copy of the specified maps. This call may be made 541 // Using our lock, make a copy of the specified maps. This call may be made
529 // on non-local threads, which necessitate the use of the lock to prevent 542 // on non-local threads, which necessitate the use of the lock to prevent
530 // the map(s) from being reallocated while they are copied. 543 // the map(s) from being reallocated while they are copied.
531 void SnapshotMaps(BirthMap* birth_map, 544 void SnapshotMaps(BirthMap* birth_map,
532 DeathMap* death_map, 545 DeathMap* death_map,
533 ParentChildSet* parent_child_set); 546 ParentChildSet* parent_child_set);
534 547
535 // This method is called by the TLS system when a thread terminates. 548 // This method is called by the TLS system when a thread terminates.
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 ParentChildPairSnapshot(); 752 ParentChildPairSnapshot();
740 explicit ParentChildPairSnapshot( 753 explicit ParentChildPairSnapshot(
741 const ThreadData::ParentChildPair& parent_child); 754 const ThreadData::ParentChildPair& parent_child);
742 ~ParentChildPairSnapshot(); 755 ~ParentChildPairSnapshot();
743 756
744 BirthOnThreadSnapshot parent; 757 BirthOnThreadSnapshot parent;
745 BirthOnThreadSnapshot child; 758 BirthOnThreadSnapshot child;
746 }; 759 };
747 760
748 //------------------------------------------------------------------------------ 761 //------------------------------------------------------------------------------
749 // A snapshotted representation of the list of ThreadData objects for a process. 762 // A snapshotted representation of the list of ThreadData objects for a process,
763 // for a single profiling phase.
764
765 struct BASE_EXPORT ProcessDataPhaseSnapshot {
766 public:
767 ProcessDataPhaseSnapshot();
768 ~ProcessDataPhaseSnapshot();
769
770 std::vector<TaskSnapshot> tasks;
771 std::vector<ParentChildPairSnapshot> descendants;
772 };
773
774 //------------------------------------------------------------------------------
775 // A snapshotted representation of the list of ThreadData objects for a process,
776 // for all profiling phases, including the current one.
750 777
751 struct BASE_EXPORT ProcessDataSnapshot { 778 struct BASE_EXPORT ProcessDataSnapshot {
752 public: 779 public:
753 ProcessDataSnapshot(); 780 ProcessDataSnapshot();
754 ~ProcessDataSnapshot(); 781 ~ProcessDataSnapshot();
755 782
756 std::vector<TaskSnapshot> tasks; 783 PhasedProcessDataSnapshots phased_process_data_snapshots;
757 std::vector<ParentChildPairSnapshot> descendants;
758 int process_id; 784 int process_id;
759 }; 785 };
760 786
761 } // namespace tracked_objects 787 } // namespace tracked_objects
762 788
763 #endif // BASE_TRACKED_OBJECTS_H_ 789 #endif // BASE_TRACKED_OBJECTS_H_
OLDNEW
« no previous file with comments | « no previous file | base/tracked_objects.cc » ('j') | base/tracked_objects.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698