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

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: 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
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.
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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 237
234 class BASE_EXPORT Births: public BirthOnThread { 238 class BASE_EXPORT Births: public BirthOnThread {
235 public: 239 public:
236 Births(const Location& location, const ThreadData& current); 240 Births(const Location& location, const ThreadData& current);
237 241
238 int birth_count() const; 242 int birth_count() const;
239 243
240 // When we have a birth we update the count for this birthplace. 244 // When we have a birth we update the count for this birthplace.
241 void RecordBirth(); 245 void RecordBirth();
242 246
247 // Subtracts a value from the birth count.
248 void SubtractBirths(int count);
249
243 private: 250 private:
244 // The number of births on this thread for our location_. 251 // The number of births on this thread for our location_.
245 int birth_count_; 252 int birth_count_;
246 253
247 DISALLOW_COPY_AND_ASSIGN(Births); 254 DISALLOW_COPY_AND_ASSIGN(Births);
248 }; 255 };
249 256
250 //------------------------------------------------------------------------------ 257 //------------------------------------------------------------------------------
251 // Basic info summarizing multiple destructions of a tracked object with a 258 // Basic info summarizing multiple destructions of a tracked object with a
252 // single birthplace (fixed Location). Used both on specific threads, and also 259 // single birthplace (fixed Location). Used both on specific threads, and also
(...skipping 17 matching lines...) Expand all
270 277
271 // Metrics accessors, used only for serialization and in tests. 278 // Metrics accessors, used only for serialization and in tests.
272 int count() const; 279 int count() const;
273 int32 run_duration_sum() const; 280 int32 run_duration_sum() const;
274 int32 run_duration_max() const; 281 int32 run_duration_max() const;
275 int32 run_duration_sample() const; 282 int32 run_duration_sample() const;
276 int32 queue_duration_sum() const; 283 int32 queue_duration_sum() const;
277 int32 queue_duration_max() const; 284 int32 queue_duration_max() const;
278 int32 queue_duration_sample() const; 285 int32 queue_duration_sample() const;
279 286
280 // Reset all tallies to zero. This is used as a hack on realtime data. 287 // Reset all tallies to zero.
281 void Clear(); 288 void Clear();
282 289
283 private: 290 private:
284 // Members are ordered from most regularly read and updated, to least 291 // Members are ordered from most regularly read and updated, to least
285 // frequently used. This might help a bit with cache lines. 292 // frequently used. This might help a bit with cache lines.
286 // Number of runs seen (divisor for calculating averages). 293 // Number of runs seen (divisor for calculating averages).
287 int count_; 294 int count_;
288 // Basic tallies, used to compute averages. 295 // Basic tallies, used to compute averages.
289 int32 run_duration_sum_; 296 int32 run_duration_sum_;
290 int32 queue_duration_sum_; 297 int32 queue_duration_sum_;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 std::string death_thread_name; 341 std::string death_thread_name;
335 }; 342 };
336 343
337 //------------------------------------------------------------------------------ 344 //------------------------------------------------------------------------------
338 // For each thread, we have a ThreadData that stores all tracking info generated 345 // 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. 346 // on this thread. This prevents the need for locking as data accumulates.
340 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. 347 // 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 348 // We also have a linked list of ThreadData instances, and that list is used to
342 // harvest data from all existing instances. 349 // harvest data from all existing instances.
343 350
351 struct ProcessDataPhaseSnapshot;
352 // Map from profiling phase number to the process-wide snapshotted
353 // representation of the list of ThreadData objects that died during the given
354 // phase.
355 typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshots;
344 struct ProcessDataSnapshot; 356 struct ProcessDataSnapshot;
345 class BASE_EXPORT TaskStopwatch; 357 class BASE_EXPORT TaskStopwatch;
346 358
347 class BASE_EXPORT ThreadData { 359 class BASE_EXPORT ThreadData {
348 public: 360 public:
349 // Current allowable states of the tracking system. The states can vary 361 // Current allowable states of the tracking system. The states can vary
350 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. 362 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED.
351 enum Status { 363 enum Status {
352 UNINITIALIZED, // PRistine, link-time state before running. 364 UNINITIALIZED, // PRistine, link-time state before running.
353 DORMANT_DURING_TESTS, // Only used during testing. 365 DORMANT_DURING_TESTS, // Only used during testing.
354 DEACTIVATED, // No longer recording profiling. 366 DEACTIVATED, // No longer recording profiling.
355 PROFILING_ACTIVE, // Recording profiles (no parent-child links). 367 PROFILING_ACTIVE, // Recording profiles (no parent-child links).
356 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. 368 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links.
357 STATUS_LAST = PROFILING_CHILDREN_ACTIVE 369 STATUS_LAST = PROFILING_CHILDREN_ACTIVE
358 }; 370 };
359 371
360 typedef std::map<Location, Births*> BirthMap; 372 typedef std::map<Location, Births*> BirthMap;
361 typedef std::map<const Births*, DeathData> DeathMap; 373 typedef std::map<Births*, DeathData> DeathMap;
362 typedef std::pair<const Births*, const Births*> ParentChildPair; 374 typedef std::pair<const Births*, const Births*> ParentChildPair;
363 typedef std::set<ParentChildPair> ParentChildSet; 375 typedef std::set<ParentChildPair> ParentChildSet;
364 typedef std::stack<const Births*> ParentStack; 376 typedef std::stack<const Births*> ParentStack;
365 377
366 // Initialize the current thread context with a new instance of ThreadData. 378 // Initialize the current thread context with a new instance of ThreadData.
367 // This is used by all threads that have names, and should be explicitly 379 // This is used by all threads that have names, and should be explicitly
368 // set *before* any births on the threads have taken place. It is generally 380 // 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. 381 // only used by the message loop, which has a well defined thread name.
370 static void InitializeThreadContext(const std::string& suggested_name); 382 static void InitializeThreadContext(const std::string& suggested_name);
371 383
372 // Using Thread Local Store, find the current instance for collecting data. 384 // 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 385 // If an instance does not exist, construct one (and remember it for use on
374 // this thread. 386 // this thread.
375 // This may return NULL if the system is disabled for any reason. 387 // This may return NULL if the system is disabled for any reason.
376 static ThreadData* Get(); 388 static ThreadData* Get();
377 389
378 // Fills |process_data| with all the recursive results in our process. 390 // Fills |process_data_snapshot| with phased snapshots of all profiling
379 static void Snapshot(ProcessDataSnapshot* process_data); 391 // phases, including the currect one, identified by |current_profiling_phase|.
Alexei Svitkine (slow) 2015/03/06 20:06:40 Nit: currect -> current I don't understand this.
vadimt 2015/03/06 21:34:58 Correct. This must be the current profiler phase.
392 static void GetProcessDataSnapshot(
393 int current_profiling_phase,
394 ProcessDataSnapshot* process_data_snapshot);
395
396 // Called when the current profiling phase, identified by |profiling_phase|,
397 // ends.
398 static void OnProfilingPhaseCompletion(int profiling_phase);
380 399
381 // Finds (or creates) a place to count births from the given location in this 400 // Finds (or creates) a place to count births from the given location in this
382 // thread, and increment that tally. 401 // thread, and increment that tally.
383 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. 402 // TallyABirthIfActive will returns NULL if the birth cannot be tallied.
384 static Births* TallyABirthIfActive(const Location& location); 403 static Births* TallyABirthIfActive(const Location& location);
385 404
386 // Records the end of a timed run of an object. The |completed_task| contains 405 // 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. 406 // 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 407 // 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 408 // 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 409 // 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. 410 // 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 411 // 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. 412 // finished). It is provided as an argument to help with testing.
394 static void TallyRunOnNamedThreadIfTracking( 413 static void TallyRunOnNamedThreadIfTracking(
395 const base::TrackingInfo& completed_task, 414 const base::TrackingInfo& completed_task,
396 const TaskStopwatch& stopwatch); 415 const TaskStopwatch& stopwatch);
397 416
398 // Record the end of a timed run of an object. The |birth| is the record for 417 // 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 418 // 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. 419 // 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 420 // The |start_of_run| is when the worker thread started to perform the run of
402 // the task. 421 // the task.
403 // The |end_of_run| was just obtained by a call to Now() (just after the task 422 // The |end_of_run| was just obtained by a call to Now() (just after the task
404 // finished). 423 // finished).
405 static void TallyRunOnWorkerThreadIfTracking( 424 static void TallyRunOnWorkerThreadIfTracking(const TrackedTime& time_posted,
406 const Births* birth, 425 const TaskStopwatch& stopwatch,
407 const TrackedTime& time_posted, 426 Births* birth);
408 const TaskStopwatch& stopwatch);
409 427
410 // Record the end of execution in region, generally corresponding to a scope 428 // Record the end of execution in region, generally corresponding to a scope
411 // being exited. 429 // being exited.
412 static void TallyRunInAScopedRegionIfTracking( 430 static void TallyRunInAScopedRegionIfTracking(const TaskStopwatch& stopwatch,
413 const Births* birth, 431 Births* birth);
414 const TaskStopwatch& stopwatch);
415 432
416 const std::string& thread_name() const { return thread_name_; } 433 const std::string& thread_name() const { return thread_name_; }
417 434
418 // Initializes all statics if needed (this initialization call should be made 435 // Initializes all statics if needed (this initialization call should be made
419 // while we are single threaded). Returns false if unable to initialize. 436 // while we are single threaded). Returns false if unable to initialize.
420 static bool Initialize(); 437 static bool Initialize();
421 438
422 // Sets internal status_. 439 // Sets internal status_.
423 // If |status| is false, then status_ is set to DEACTIVATED. 440 // If |status| is false, then status_ is set to DEACTIVATED.
424 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or 441 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 static ThreadData* first(); 516 static ThreadData* first();
500 517
501 // Iterate through the null terminated list of ThreadData instances. 518 // Iterate through the null terminated list of ThreadData instances.
502 ThreadData* next() const; 519 ThreadData* next() const;
503 520
504 521
505 // In this thread's data, record a new birth. 522 // In this thread's data, record a new birth.
506 Births* TallyABirth(const Location& location); 523 Births* TallyABirth(const Location& location);
507 524
508 // Find a place to record a death on this thread. 525 // Find a place to record a death on this thread.
509 void TallyADeath(const Births& birth, 526 void TallyADeath(int32 queue_duration,
510 int32 queue_duration, 527 const TaskStopwatch& stopwatch,
511 const TaskStopwatch& stopwatch); 528 Births* birth);
512 529
513 // 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
514 // 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
515 // track of the number of living instances of the task. 532 // track of the number of living instances of the task. If |reset| is true,
516 static void SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data, 533 // remove all recorded deaths.
517 BirthCountMap* birth_counts); 534 static void SnapshotAllExecutedTasks(
535 bool reset,
536 ProcessDataPhaseSnapshot* process_data_phase,
537 BirthCountMap* birth_counts);
538
539 // Fills |process_data_phase| with all the recursive results in our process.
540 // If |reset| is true, remove all recorded deaths.
541 static void Snapshot(bool reset,
542 ProcessDataPhaseSnapshot* process_data_phase);
518 543
519 // Snapshots (under a lock) the profiled data for the tasks for this thread 544 // 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 545 // 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 546 // 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 547 // 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 548 // 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. 549 // births for the task that have not yet been balanced by a death. If |reset|
525 void SnapshotExecutedTasks(ProcessDataSnapshot* process_data, 550 // is true, remove all recorded deaths.
551 void SnapshotExecutedTasks(bool reset,
552 ProcessDataPhaseSnapshot* process_data_phase,
526 BirthCountMap* birth_counts); 553 BirthCountMap* birth_counts);
527 554
528 // Using our lock, make a copy of the specified maps. This call may be made 555 // 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 556 // on non-local threads, which necessitate the use of the lock to prevent
530 // the map(s) from being reallocated while they are copied. 557 // the map(s) from being reallocated while they are copied. If |reset| is
531 void SnapshotMaps(BirthMap* birth_map, 558 // true, remove all recorded deaths.
559 void SnapshotMaps(bool reset,
560 BirthMap* birth_map,
532 DeathMap* death_map, 561 DeathMap* death_map,
533 ParentChildSet* parent_child_set); 562 ParentChildSet* parent_child_set);
534 563
535 // This method is called by the TLS system when a thread terminates. 564 // This method is called by the TLS system when a thread terminates.
536 // The argument may be NULL if this thread has never tracked a birth or death. 565 // The argument may be NULL if this thread has never tracked a birth or death.
537 static void OnThreadTermination(void* thread_data); 566 static void OnThreadTermination(void* thread_data);
538 567
539 // This method should be called when a worker thread terminates, so that we 568 // This method should be called when a worker thread terminates, so that we
540 // can save all the thread data into a cache of reusable ThreadData instances. 569 // can save all the thread data into a cache of reusable ThreadData instances.
541 void OnThreadTerminationCleanup(); 570 void OnThreadTerminationCleanup();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 618
590 // Protection for access to all_thread_data_list_head_, and to 619 // Protection for access to all_thread_data_list_head_, and to
591 // unregistered_thread_data_pool_. This lock is leaked at shutdown. 620 // unregistered_thread_data_pool_. This lock is leaked at shutdown.
592 // The lock is very infrequently used, so we can afford to just make a lazy 621 // The lock is very infrequently used, so we can afford to just make a lazy
593 // instance and be safe. 622 // instance and be safe.
594 static base::LazyInstance<base::Lock>::Leaky list_lock_; 623 static base::LazyInstance<base::Lock>::Leaky list_lock_;
595 624
596 // We set status_ to SHUTDOWN when we shut down the tracking service. 625 // We set status_ to SHUTDOWN when we shut down the tracking service.
597 static Status status_; 626 static Status status_;
598 627
628 // Process data snapshots for completed profiling phases.
629 static base::LazyInstance<PhasedProcessDataSnapshots>
630 completed_phases_snapshots_;
631
599 // Link to next instance (null terminated list). Used to globally track all 632 // Link to next instance (null terminated list). Used to globally track all
600 // registered instances (corresponds to all registered threads where we keep 633 // registered instances (corresponds to all registered threads where we keep
601 // data). 634 // data).
602 ThreadData* next_; 635 ThreadData* next_;
603 636
604 // Pointer to another ThreadData instance for a Worker-Thread that has been 637 // Pointer to another ThreadData instance for a Worker-Thread that has been
605 // retired (its thread was terminated). This value is non-NULL only for a 638 // retired (its thread was terminated). This value is non-NULL only for a
606 // retired ThreadData associated with a Worker-Thread. 639 // retired ThreadData associated with a Worker-Thread.
607 ThreadData* next_retired_worker_; 640 ThreadData* next_retired_worker_;
608 641
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 ParentChildPairSnapshot(); 772 ParentChildPairSnapshot();
740 explicit ParentChildPairSnapshot( 773 explicit ParentChildPairSnapshot(
741 const ThreadData::ParentChildPair& parent_child); 774 const ThreadData::ParentChildPair& parent_child);
742 ~ParentChildPairSnapshot(); 775 ~ParentChildPairSnapshot();
743 776
744 BirthOnThreadSnapshot parent; 777 BirthOnThreadSnapshot parent;
745 BirthOnThreadSnapshot child; 778 BirthOnThreadSnapshot child;
746 }; 779 };
747 780
748 //------------------------------------------------------------------------------ 781 //------------------------------------------------------------------------------
749 // A snapshotted representation of the list of ThreadData objects for a process. 782 // A snapshotted representation of the list of ThreadData objects for a process,
783 // for a single profiling phase.
784
785 struct BASE_EXPORT ProcessDataPhaseSnapshot {
786 public:
787 ProcessDataPhaseSnapshot();
788 ~ProcessDataPhaseSnapshot();
789
790 std::vector<TaskSnapshot> tasks;
791 std::vector<ParentChildPairSnapshot> descendants;
792 };
793
794 //------------------------------------------------------------------------------
795 // A snapshotted representation of the list of ThreadData objects for a process,
796 // for all profiling phases, including the current one.
750 797
751 struct BASE_EXPORT ProcessDataSnapshot { 798 struct BASE_EXPORT ProcessDataSnapshot {
752 public: 799 public:
753 ProcessDataSnapshot(); 800 ProcessDataSnapshot();
754 ~ProcessDataSnapshot(); 801 ~ProcessDataSnapshot();
755 802
756 std::vector<TaskSnapshot> tasks; 803 PhasedProcessDataSnapshots phased_process_data_snapshots;
757 std::vector<ParentChildPairSnapshot> descendants;
758 int process_id; 804 int process_id;
759 }; 805 };
760 806
761 } // namespace tracked_objects 807 } // namespace tracked_objects
762 808
763 #endif // BASE_TRACKED_OBJECTS_H_ 809 #endif // BASE_TRACKED_OBJECTS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698