| OLD | NEW |
| 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> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/base_export.h" | 15 #include "base/base_export.h" |
| 16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
| 17 #include "base/containers/hash_tables.h" | 17 #include "base/containers/hash_tables.h" |
| 18 #include "base/gtest_prod_util.h" | 18 #include "base/gtest_prod_util.h" |
| 19 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
| 20 #include "base/location.h" | 20 #include "base/location.h" |
| 21 #include "base/process/process_handle.h" | 21 #include "base/process/process_handle.h" |
| 22 #include "base/profiler/alternate_timer.h" | 22 #include "base/profiler/alternate_timer.h" |
| 23 #include "base/profiler/tracked_time.h" | 23 #include "base/profiler/tracked_time.h" |
| 24 #include "base/synchronization/lock.h" | 24 #include "base/synchronization/lock.h" |
| 25 #include "base/threading/thread_checker.h" |
| 25 #include "base/threading/thread_local_storage.h" | 26 #include "base/threading/thread_local_storage.h" |
| 26 | 27 |
| 27 namespace base { | 28 namespace base { |
| 28 struct TrackingInfo; | 29 struct TrackingInfo; |
| 29 } | 30 } |
| 30 | 31 |
| 31 // TrackedObjects provides a database of stats about objects (generally Tasks) | 32 // TrackedObjects provides a database of stats about objects (generally Tasks) |
| 32 // that are tracked. Tracking means their birth, death, duration, birth thread, | 33 // that are tracked. Tracking means their birth, death, duration, birth thread, |
| 33 // death thread, and birth place are recorded. This data is carefully spread | 34 // death thread, and birth place are recorded. This data is carefully spread |
| 34 // across a series of objects so that the counts and times can be rapidly | 35 // across a series of objects so that the counts and times can be rapidly |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 // can find out a Task's location of birth, and thread of birth, without using | 79 // can find out a Task's location of birth, and thread of birth, without using |
| 79 // any locks, as all that data is constant across the life of the process. | 80 // any locks, as all that data is constant across the life of the process. |
| 80 // | 81 // |
| 81 // The above work *could* also be done for any other object as well by calling | 82 // The above work *could* also be done for any other object as well by calling |
| 82 // TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. | 83 // TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. |
| 83 // | 84 // |
| 84 // The amount of memory used in the above data structures depends on how many | 85 // The amount of memory used in the above data structures depends on how many |
| 85 // threads there are, and how many Locations of construction there are. | 86 // threads there are, and how many Locations of construction there are. |
| 86 // Fortunately, we don't use memory that is the product of those two counts, but | 87 // Fortunately, we don't use memory that is the product of those two counts, but |
| 87 // rather we only need one Births instance for each thread that constructs an | 88 // rather we only need one Births instance for each thread that constructs an |
| 88 // instance at a Location. In many cases, instances are only created on one | 89 // instance at a Location. In many cases, instances are only created on one |
| 89 // thread, so the memory utilization is actually fairly restrained. | 90 // thread, so the memory utilization is actually fairly restrained. |
| 90 // | 91 // |
| 91 // Lastly, when an instance is deleted, the final tallies of statistics are | 92 // Lastly, when an instance is deleted, the final tallies of statistics are |
| 92 // carefully accumulated. That tallying writes into slots (members) in a | 93 // carefully accumulated. That tallying writes into slots (members) in a |
| 93 // collection of DeathData instances. For each birth place Location that is | 94 // collection of DeathData instances. For each birth place Location that is |
| 94 // destroyed on a thread, there is a DeathData instance to record the additional | 95 // destroyed on a thread, there is a DeathData instance to record the additional |
| 95 // death count, as well as accumulate the run-time and queue-time durations for | 96 // death count, as well as accumulate the run-time and queue-time durations for |
| 96 // the instance as it is destroyed (dies). By maintaining a single place to | 97 // the instance as it is destroyed (dies). By maintaining a single place to |
| 97 // aggregate this running sum *only* for the given thread, we avoid the need to | 98 // aggregate this running sum *only* for the given thread, we avoid the need to |
| 98 // lock such DeathData instances. (i.e., these accumulated stats in a DeathData | 99 // lock such DeathData instances. (i.e., these accumulated stats in a DeathData |
| 99 // instance are exclusively updated by the singular owning thread). | 100 // instance are exclusively updated by the singular owning thread). |
| 100 // | 101 // |
| 101 // With the above life cycle description complete, the major remaining detail | 102 // With the above life cycle description complete, the major remaining detail |
| 102 // is explaining how each thread maintains a list of DeathData instances, and | 103 // is explaining how each thread maintains a list of DeathData instances, and |
| 103 // of Births instances, and is able to avoid additional (redundant/unnecessary) | 104 // of Births instances, and is able to avoid additional (redundant/unnecessary) |
| 104 // allocations. | 105 // allocations. |
| 105 // | 106 // |
| 106 // Each thread maintains a list of data items specific to that thread in a | 107 // Each thread maintains a list of data items specific to that thread in a |
| 107 // ThreadData instance (for that specific thread only). The two critical items | 108 // ThreadData instance (for that specific thread only). The two critical items |
| 108 // are lists of DeathData and Births instances. These lists are maintained in | 109 // are lists of DeathData and Births instances. These lists are maintained in |
| 109 // STL maps, which are indexed by Location. As noted earlier, we can compare | 110 // STL maps, which are indexed by Location. As noted earlier, we can compare |
| 110 // locations very efficiently as we consider the underlying data (file, | 111 // locations very efficiently as we consider the underlying data (file, |
| 111 // function, line) to be atoms, and hence pointer comparison is used rather than | 112 // function, line) to be atoms, and hence pointer comparison is used rather than |
| 112 // (slow) string comparisons. | 113 // (slow) string comparisons. |
| 113 // | 114 // |
| 114 // To provide a mechanism for iterating over all "known threads," which means | 115 // To provide a mechanism for iterating over all "known threads," which means |
| 115 // threads that have recorded a birth or a death, we create a singly linked list | 116 // threads that have recorded a birth or a death, we create a singly linked list |
| 116 // of ThreadData instances. Each such instance maintains a pointer to the next | 117 // of ThreadData instances. Each such instance maintains a pointer to the next |
| 117 // one. A static member of ThreadData provides a pointer to the first item on | 118 // one. A static member of ThreadData provides a pointer to the first item on |
| 118 // this global list, and access via that all_thread_data_list_head_ item | 119 // this global list, and access via that all_thread_data_list_head_ item |
| 119 // requires the use of the list_lock_. | 120 // requires the use of the list_lock_. |
| 120 // When new ThreadData instances is added to the global list, it is pre-pended, | 121 // When new ThreadData instances is added to the global list, it is pre-pended, |
| 121 // which ensures that any prior acquisition of the list is valid (i.e., the | 122 // which ensures that any prior acquisition of the list is valid (i.e., the |
| 122 // holder can iterate over it without fear of it changing, or the necessity of | 123 // holder can iterate over it without fear of it changing, or the necessity of |
| 123 // using an additional lock. Iterations are actually pretty rare (used | 124 // using an additional lock. Iterations are actually pretty rare (used |
| 124 // primarily for cleanup, or snapshotting data for display), so this lock has | 125 // primarily for cleanup, or snapshotting data for display), so this lock has |
| 125 // very little global performance impact. | 126 // very little global performance impact. |
| 126 // | 127 // |
| (...skipping 14 matching lines...) Expand all Loading... |
| 141 // (3) the snapshotted data. | 142 // (3) the snapshotted data. |
| 142 // | 143 // |
| 143 // For a given birth location, information about births is spread across data | 144 // For a given birth location, information about births is spread across data |
| 144 // structures that are asynchronously changing on various threads. For | 145 // structures that are asynchronously changing on various threads. For |
| 145 // serialization and display purposes, we need to construct TaskSnapshot | 146 // serialization and display purposes, we need to construct TaskSnapshot |
| 146 // instances for each combination of birth thread, death thread, and location, | 147 // instances for each combination of birth thread, death thread, and location, |
| 147 // 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 |
| 148 // TaskSnapshot instances, so that such instances can be sorted and | 149 // TaskSnapshot instances, so that such instances can be sorted and |
| 149 // aggregated (and remain frozen during our processing). | 150 // aggregated (and remain frozen during our processing). |
| 150 // | 151 // |
| 151 // Profiling consists of phases. The concrete phase in the sequence of phases is | 152 // Profiling consists of phases. The concrete phase in the sequence of phases |
| 152 // identified by its 0-based index. | 153 // is identified by its 0-based index. |
| 153 // | 154 // |
| 154 // The ProcessDataPhaseSnapshot struct is a serialized representation of the | 155 // The ProcessDataPhaseSnapshot struct is a serialized representation of the |
| 155 // 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 |
| 156 // holds a set of TaskSnapshots and tracks parent/child relationships for the | 157 // holds a set of TaskSnapshots and tracks parent/child relationships for the |
| 157 // executed tasks. The statistics in a snapshot are gathered asynhcronously | 158 // executed tasks. The statistics in a snapshot are gathered asynhcronously |
| 158 // relative to their ongoing updates. | 159 // relative to their ongoing updates. |
| 159 // It is possible, though highly unlikely, that stats could be incorrectly | 160 // It is possible, though highly unlikely, that stats could be incorrectly |
| 160 // recorded by this process (all data is held in 32 bit ints, but we are not | 161 // recorded by this process (all data is held in 32 bit ints, but we are not |
| 161 // atomically collecting all data, so we could have count that does not, for | 162 // atomically collecting all data, so we could have count that does not, for |
| 162 // example, match with the number of durations we accumulated). The advantage | 163 // example, match with the number of durations we accumulated). The advantage |
| 163 // to having fast (non-atomic) updates of the data outweighs the minimal risk of | 164 // to having fast (non-atomic) updates of the data outweighs the minimal risk of |
| 164 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, | 165 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, |
| 165 // not the underlying and ongoing statistic). In contrast, pointer data that | 166 // not the underlying and ongoing statistic). In contrast, pointer data that |
| 166 // is accessed during snapshotting is completely invariant, and hence is | 167 // is accessed during snapshotting is completely invariant, and hence is |
| 167 // perfectly acquired (i.e., no potential corruption, and no risk of a bad | 168 // perfectly acquired (i.e., no potential corruption, and no risk of a bad |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 void RecordBirth(); | 248 void RecordBirth(); |
| 248 | 249 |
| 249 private: | 250 private: |
| 250 // The number of births on this thread for our location_. | 251 // The number of births on this thread for our location_. |
| 251 int birth_count_; | 252 int birth_count_; |
| 252 | 253 |
| 253 DISALLOW_COPY_AND_ASSIGN(Births); | 254 DISALLOW_COPY_AND_ASSIGN(Births); |
| 254 }; | 255 }; |
| 255 | 256 |
| 256 //------------------------------------------------------------------------------ | 257 //------------------------------------------------------------------------------ |
| 257 // Basic info summarizing multiple destructions of a tracked object with a | 258 // A "snapshotted" representation of the DeathData class. |
| 258 // single birthplace (fixed Location). Used both on specific threads, and also | 259 |
| 259 // in snapshots when integrating assembled data. | 260 struct BASE_EXPORT DeathDataSnapshot { |
| 261 DeathDataSnapshot(); |
| 262 |
| 263 // Constructs the snapshot from individual values. |
| 264 // The alternative would be taking a DeathData parameter, but this would |
| 265 // create a loop since DeathData indirectly refers DeathDataSnapshot. Passing |
| 266 // a wrapper structure as a param or using an empty constructor for |
| 267 // snapshotting DeathData would be less efficient. |
| 268 DeathDataSnapshot(int count, |
| 269 int32 run_duration_sum, |
| 270 int32 run_duration_max, |
| 271 int32 run_duration_sample, |
| 272 int32 queue_duration_sum, |
| 273 int32 queue_duration_max, |
| 274 int32 queue_duration_sample); |
| 275 ~DeathDataSnapshot(); |
| 276 |
| 277 // Calculates and returns the delta between this snapshot and an earlier |
| 278 // snapshot of the same task |older|. |
| 279 DeathDataSnapshot Delta(const DeathDataSnapshot& older) const; |
| 280 |
| 281 int count; |
| 282 int32 run_duration_sum; |
| 283 int32 run_duration_max; |
| 284 int32 run_duration_sample; |
| 285 int32 queue_duration_sum; |
| 286 int32 queue_duration_max; |
| 287 int32 queue_duration_sample; |
| 288 }; |
| 289 |
| 290 //------------------------------------------------------------------------------ |
| 291 // A "snapshotted" representation of the DeathData for a particular profiling |
| 292 // phase. Used as an element of the list of phase snapshots owned by DeathData. |
| 293 |
| 294 struct DeathDataPhaseSnapshot { |
| 295 DeathDataPhaseSnapshot(int profiling_phase, |
| 296 int count, |
| 297 int32 run_duration_sum, |
| 298 int32 run_duration_max, |
| 299 int32 run_duration_sample, |
| 300 int32 queue_duration_sum, |
| 301 int32 queue_duration_max, |
| 302 int32 queue_duration_sample, |
| 303 const DeathDataPhaseSnapshot* prev); |
| 304 |
| 305 // Profiling phase at which completion this snapshot was taken. |
| 306 int profiling_phase; |
| 307 |
| 308 // Death data snapshot. |
| 309 DeathDataSnapshot death_data; |
| 310 |
| 311 // Pointer to a snapshot from the previous phase. |
| 312 const DeathDataPhaseSnapshot* prev; |
| 313 }; |
| 314 |
| 315 //------------------------------------------------------------------------------ |
| 316 // Information about deaths of a task on a given thread, called "death thread". |
| 317 // Access to members of this class is never protected by a lock. The fields |
| 318 // are accessed in such a way that corruptions resulting from race conditions |
| 319 // are not significant, and don't accumulate as a result of multiple accesses. |
| 320 // All invocations of DeathData::OnProfilingPhaseCompleted and |
| 321 // ThreadData::SnapshotMaps (which takes DeathData snapshot) in a given process |
| 322 // must be called from the same thread. It doesn't matter what thread it is, but |
| 323 // it's important the same thread is used as a snapshot thread during the whole |
| 324 // process lifetime. All fields except sample_probability_count_ can be |
| 325 // snapshotted. |
| 260 | 326 |
| 261 class BASE_EXPORT DeathData { | 327 class BASE_EXPORT DeathData { |
| 262 public: | 328 public: |
| 263 // Default initializer. | |
| 264 DeathData(); | 329 DeathData(); |
| 265 | 330 DeathData(const DeathData& other); |
| 266 // When deaths have not yet taken place, and we gather data from all the | 331 ~DeathData(); |
| 267 // threads, we create DeathData stats that tally the number of births without | |
| 268 // a corresponding death. | |
| 269 explicit DeathData(int count); | |
| 270 | 332 |
| 271 // Update stats for a task destruction (death) that had a Run() time of | 333 // Update stats for a task destruction (death) that had a Run() time of |
| 272 // |duration|, and has had a queueing delay of |queue_duration|. | 334 // |duration|, and has had a queueing delay of |queue_duration|. |
| 273 void RecordDeath(const int32 queue_duration, | 335 void RecordDeath(const int32 queue_duration, |
| 274 const int32 run_duration, | 336 const int32 run_duration, |
| 275 const uint32 random_number); | 337 const uint32 random_number); |
| 276 | 338 |
| 277 // Metrics accessors, used only for serialization and in tests. | 339 // Metrics and past snapshots accessors, used only for serialization and in |
| 340 // tests. |
| 278 int count() const; | 341 int count() const; |
| 279 int32 run_duration_sum() const; | 342 int32 run_duration_sum() const; |
| 280 int32 run_duration_max() const; | 343 int32 run_duration_max() const; |
| 281 int32 run_duration_sample() const; | 344 int32 run_duration_sample() const; |
| 282 int32 queue_duration_sum() const; | 345 int32 queue_duration_sum() const; |
| 283 int32 queue_duration_max() const; | 346 int32 queue_duration_max() const; |
| 284 int32 queue_duration_sample() const; | 347 int32 queue_duration_sample() const; |
| 348 const DeathDataPhaseSnapshot* last_phase_snapshot() const; |
| 285 | 349 |
| 286 // Reset all tallies to zero. This is used as a hack on realtime data. | 350 // Called when the current profiling phase, identified by |profiling_phase|, |
| 287 void Clear(); | 351 // ends. |
| 352 // Must be called only on the snapshot thread. |
| 353 void OnProfilingPhaseCompleted(int profiling_phase); |
| 288 | 354 |
| 289 private: | 355 private: |
| 290 // Members are ordered from most regularly read and updated, to least | 356 // Members are ordered from most regularly read and updated, to least |
| 291 // frequently used. This might help a bit with cache lines. | 357 // frequently used. This might help a bit with cache lines. |
| 292 // Number of runs seen (divisor for calculating averages). | 358 // Number of runs seen (divisor for calculating averages). |
| 359 // Can be incremented only on the death thread. |
| 293 int count_; | 360 int count_; |
| 294 // Basic tallies, used to compute averages. | 361 |
| 362 // Count used in determining probability of selecting exec/queue times from a |
| 363 // recorded death as samples. |
| 364 // Gets incremented only on the death thread, but can be set to 0 by |
| 365 // OnProfilingPhaseCompleted() on the snapshot thread. |
| 366 int sample_probability_count_; |
| 367 |
| 368 // Basic tallies, used to compute averages. Can be incremented only on the |
| 369 // death thread. |
| 295 int32 run_duration_sum_; | 370 int32 run_duration_sum_; |
| 296 int32 queue_duration_sum_; | 371 int32 queue_duration_sum_; |
| 297 // Max values, used by local visualization routines. These are often read, | 372 // Max values, used by local visualization routines. These are often read, |
| 298 // but rarely updated. | 373 // but rarely updated. The max values get assigned only on the death thread, |
| 374 // but these fields can be set to 0 by OnProfilingPhaseCompleted() on the |
| 375 // snapshot thread. |
| 299 int32 run_duration_max_; | 376 int32 run_duration_max_; |
| 300 int32 queue_duration_max_; | 377 int32 queue_duration_max_; |
| 301 // Samples, used by crowd sourcing gatherers. These are almost never read, | 378 // Samples, used by crowd sourcing gatherers. These are almost never read, |
| 302 // and rarely updated. | 379 // and rarely updated. They can be modified only on the death thread. |
| 303 int32 run_duration_sample_; | 380 int32 run_duration_sample_; |
| 304 int32 queue_duration_sample_; | 381 int32 queue_duration_sample_; |
| 382 |
| 383 // Snapshot of this death data made at the last profiling phase completion, if |
| 384 // any. DeathData owns the whole list starting with this pointer. |
| 385 // Can be accessed only on the snapshot thread. |
| 386 const DeathDataPhaseSnapshot* last_phase_snapshot_; |
| 387 |
| 388 DISALLOW_ASSIGN(DeathData); |
| 305 }; | 389 }; |
| 306 | 390 |
| 307 //------------------------------------------------------------------------------ | 391 //------------------------------------------------------------------------------ |
| 308 // A "snapshotted" representation of the DeathData class. | |
| 309 | |
| 310 struct BASE_EXPORT DeathDataSnapshot { | |
| 311 DeathDataSnapshot(); | |
| 312 explicit DeathDataSnapshot(const DeathData& death_data); | |
| 313 ~DeathDataSnapshot(); | |
| 314 | |
| 315 int count; | |
| 316 int32 run_duration_sum; | |
| 317 int32 run_duration_max; | |
| 318 int32 run_duration_sample; | |
| 319 int32 queue_duration_sum; | |
| 320 int32 queue_duration_max; | |
| 321 int32 queue_duration_sample; | |
| 322 }; | |
| 323 | |
| 324 //------------------------------------------------------------------------------ | |
| 325 // A temporary collection of data that can be sorted and summarized. It is | 392 // A temporary collection of data that can be sorted and summarized. It is |
| 326 // gathered (carefully) from many threads. Instances are held in arrays and | 393 // gathered (carefully) from many threads. Instances are held in arrays and |
| 327 // processed, filtered, and rendered. | 394 // processed, filtered, and rendered. |
| 328 // The source of this data was collected on many threads, and is asynchronously | 395 // The source of this data was collected on many threads, and is asynchronously |
| 329 // changing. The data in this instance is not asynchronously changing. | 396 // changing. The data in this instance is not asynchronously changing. |
| 330 | 397 |
| 331 struct BASE_EXPORT TaskSnapshot { | 398 struct BASE_EXPORT TaskSnapshot { |
| 332 TaskSnapshot(); | 399 TaskSnapshot(); |
| 333 TaskSnapshot(const BirthOnThread& birth, | 400 TaskSnapshot(const BirthOnThreadSnapshot& birth, |
| 334 const DeathData& death_data, | 401 const DeathDataSnapshot& death_data, |
| 335 const std::string& death_thread_name); | 402 const std::string& death_thread_name); |
| 336 ~TaskSnapshot(); | 403 ~TaskSnapshot(); |
| 337 | 404 |
| 338 BirthOnThreadSnapshot birth; | 405 BirthOnThreadSnapshot birth; |
| 406 // Delta between death data for a thread for a certain profiling phase and the |
| 407 // snapshot for the pervious phase, if any. Otherwise, just a snapshot. |
| 339 DeathDataSnapshot death_data; | 408 DeathDataSnapshot death_data; |
| 340 std::string death_thread_name; | 409 std::string death_thread_name; |
| 341 }; | 410 }; |
| 342 | 411 |
| 343 //------------------------------------------------------------------------------ | 412 //------------------------------------------------------------------------------ |
| 344 // For each thread, we have a ThreadData that stores all tracking info generated | 413 // For each thread, we have a ThreadData that stores all tracking info generated |
| 345 // on this thread. This prevents the need for locking as data accumulates. | 414 // on this thread. This prevents the need for locking as data accumulates. |
| 346 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. | 415 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. |
| 347 // We also have a linked list of ThreadData instances, and that list is used to | 416 // We also have a linked list of ThreadData instances, and that list is used to |
| 348 // harvest data from all existing instances. | 417 // harvest data from all existing instances. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 // only used by the message loop, which has a well defined thread name. | 450 // only used by the message loop, which has a well defined thread name. |
| 382 static void InitializeThreadContext(const std::string& suggested_name); | 451 static void InitializeThreadContext(const std::string& suggested_name); |
| 383 | 452 |
| 384 // Using Thread Local Store, find the current instance for collecting data. | 453 // Using Thread Local Store, find the current instance for collecting data. |
| 385 // If an instance does not exist, construct one (and remember it for use on | 454 // If an instance does not exist, construct one (and remember it for use on |
| 386 // this thread. | 455 // this thread. |
| 387 // This may return NULL if the system is disabled for any reason. | 456 // This may return NULL if the system is disabled for any reason. |
| 388 static ThreadData* Get(); | 457 static ThreadData* Get(); |
| 389 | 458 |
| 390 // Fills |process_data_snapshot| with phased snapshots of all profiling | 459 // Fills |process_data_snapshot| with phased snapshots of all profiling |
| 391 // phases, including the current one. | 460 // phases, including the current one, identified by |current_profiling_phase|. |
| 392 static void Snapshot(ProcessDataSnapshot* process_data_snapshot); | 461 // |current_profiling_phase| is necessary because a child process can start |
| 462 // after several phase-changing events, so it needs to receive the current |
| 463 // phase number from the browser process to fill the correct entry for the |
| 464 // current phase in the |process_data_snapshot| map. |
| 465 static void Snapshot(int current_profiling_phase, |
| 466 ProcessDataSnapshot* process_data_snapshot); |
| 467 |
| 468 // Called when the current profiling phase, identified by |profiling_phase|, |
| 469 // ends. |
| 470 // |profiling_phase| is necessary because a child process can start after |
| 471 // several phase-changing events, so it needs to receive the phase number from |
| 472 // the browser process to fill the correct entry in the |
| 473 // completed_phases_snapshots_ map. |
| 474 static void OnProfilingPhaseCompleted(int profiling_phase); |
| 393 | 475 |
| 394 // Finds (or creates) a place to count births from the given location in this | 476 // Finds (or creates) a place to count births from the given location in this |
| 395 // thread, and increment that tally. | 477 // thread, and increment that tally. |
| 396 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. | 478 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. |
| 397 static Births* TallyABirthIfActive(const Location& location); | 479 static Births* TallyABirthIfActive(const Location& location); |
| 398 | 480 |
| 399 // Records the end of a timed run of an object. The |completed_task| contains | 481 // Records the end of a timed run of an object. The |completed_task| contains |
| 400 // a pointer to a Births, the time_posted, and a delayed_start_time if any. | 482 // a pointer to a Births, the time_posted, and a delayed_start_time if any. |
| 401 // The |start_of_run| indicates when we started to perform the run of the | 483 // The |start_of_run| indicates when we started to perform the run of the |
| 402 // task. The delayed_start_time is non-null for tasks that were posted as | 484 // task. The delayed_start_time is non-null for tasks that were posted as |
| 403 // delayed tasks, and it indicates when the task should have run (i.e., when | 485 // delayed tasks, and it indicates when the task should have run (i.e., when |
| 404 // it should have posted out of the timer queue, and into the work queue. | 486 // it should have posted out of the timer queue, and into the work queue. |
| 405 // The |end_of_run| was just obtained by a call to Now() (just after the task | 487 // The |end_of_run| was just obtained by a call to Now() (just after the task |
| 406 // finished). It is provided as an argument to help with testing. | 488 // finished). It is provided as an argument to help with testing. |
| 407 static void TallyRunOnNamedThreadIfTracking( | 489 static void TallyRunOnNamedThreadIfTracking( |
| 408 const base::TrackingInfo& completed_task, | 490 const base::TrackingInfo& completed_task, |
| 409 const TaskStopwatch& stopwatch); | 491 const TaskStopwatch& stopwatch); |
| 410 | 492 |
| 411 // Record the end of a timed run of an object. The |birth| is the record for | 493 // Record the end of a timed run of an object. The |birth| is the record for |
| 412 // the instance, the |time_posted| records that instant, which is presumed to | 494 // the instance, the |time_posted| records that instant, which is presumed to |
| 413 // be when the task was posted into a queue to run on a worker thread. | 495 // be when the task was posted into a queue to run on a worker thread. |
| 414 // The |start_of_run| is when the worker thread started to perform the run of | 496 // The |start_of_run| is when the worker thread started to perform the run of |
| 415 // the task. | 497 // the task. |
| 416 // The |end_of_run| was just obtained by a call to Now() (just after the task | 498 // The |end_of_run| was just obtained by a call to Now() (just after the task |
| 417 // finished). | 499 // finished). |
| 418 static void TallyRunOnWorkerThreadIfTracking(const Births* birth, | 500 static void TallyRunOnWorkerThreadIfTracking(const Births* births, |
| 419 const TrackedTime& time_posted, | 501 const TrackedTime& time_posted, |
| 420 const TaskStopwatch& stopwatch); | 502 const TaskStopwatch& stopwatch); |
| 421 | 503 |
| 422 // Record the end of execution in region, generally corresponding to a scope | 504 // Record the end of execution in region, generally corresponding to a scope |
| 423 // being exited. | 505 // being exited. |
| 424 static void TallyRunInAScopedRegionIfTracking(const Births* birth, | 506 static void TallyRunInAScopedRegionIfTracking(const Births* births, |
| 425 const TaskStopwatch& stopwatch); | 507 const TaskStopwatch& stopwatch); |
| 426 | 508 |
| 427 const std::string& thread_name() const { return thread_name_; } | 509 const std::string& thread_name() const { return thread_name_; } |
| 428 | 510 |
| 429 // Initializes all statics if needed (this initialization call should be made | 511 // Initializes all statics if needed (this initialization call should be made |
| 430 // while we are single threaded). Returns false if unable to initialize. | 512 // while we are single threaded). Returns false if unable to initialize. |
| 431 static bool Initialize(); | 513 static bool Initialize(); |
| 432 | 514 |
| 433 // Sets internal status_. | 515 // Sets internal status_. |
| 434 // If |status| is false, then status_ is set to DEACTIVATED. | 516 // If |status| is false, then status_ is set to DEACTIVATED. |
| 435 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or | 517 // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or |
| 436 // PROFILING_CHILDREN_ACTIVE. | 518 // PROFILING_CHILDREN_ACTIVE. |
| 437 // If tracking is not compiled in, this function will return false. | 519 // If tracking is not compiled in, this function will return false. |
| 438 // If parent-child tracking is not compiled in, then an attempt to set the | 520 // If parent-child tracking is not compiled in, then an attempt to set the |
| 439 // status to PROFILING_CHILDREN_ACTIVE will only result in a status of | 521 // status to PROFILING_CHILDREN_ACTIVE will only result in a status of |
| 440 // PROFILING_ACTIVE (i.e., it can't be set to a higher level than what is | 522 // PROFILING_ACTIVE (i.e., it can't be set to a higher level than what is |
| 441 // compiled into the binary, and parent-child tracking at the | 523 // compiled into the binary, and parent-child tracking at the |
| 442 // PROFILING_CHILDREN_ACTIVE level might not be compiled in). | 524 // PROFILING_CHILDREN_ACTIVE level might not be compiled in). |
| 443 static bool InitializeAndSetTrackingStatus(Status status); | 525 static bool InitializeAndSetTrackingStatus(Status status); |
| 444 | 526 |
| 445 static Status status(); | 527 static Status status(); |
| 446 | 528 |
| 447 // Indicate if any sort of profiling is being done (i.e., we are more than | 529 // Indicate if any sort of profiling is being done (i.e., we are more than |
| 448 // DEACTIVATED). | 530 // DEACTIVATED). |
| 449 static bool TrackingStatus(); | 531 static bool TrackingStatus(); |
| 450 | 532 |
| 451 // For testing only, indicate if the status of parent-child tracking is turned | 533 // For testing only, indicate if the status of parent-child tracking is turned |
| 452 // on. This is currently a compiled option, atop TrackingStatus(). | 534 // on. This is currently a compiled option, atop TrackingStatus(). |
| 453 static bool TrackingParentChildStatus(); | 535 static bool TrackingParentChildStatus(); |
| 454 | 536 |
| 455 // Marks a start of a tracked run. It's super fast when tracking is disabled, | 537 // Marks a start of a tracked run. It's super fast when tracking is disabled, |
| 456 // and has some internal side effects when we are tracking, so that we can | 538 // and has some internal side effects when we are tracking, so that we can |
| 457 // deduce the amount of time accumulated outside of execution of tracked runs. | 539 // deduce the amount of time accumulated outside of execution of tracked runs. |
| 458 // The task that will be tracked is passed in as |parent| so that parent-child | 540 // The task that will be tracked is passed in as |parent| so that parent-child |
| 459 // relationships can be (optionally) calculated. | 541 // relationships can be (optionally) calculated. |
| 460 static void PrepareForStartOfRun(const Births* parent); | 542 static void PrepareForStartOfRun(const Births* parent); |
| 461 | 543 |
| 462 // Enables profiler timing. | 544 // Enables profiler timing. |
| 463 static void EnableProfilerTiming(); | 545 static void EnableProfilerTiming(); |
| 464 | 546 |
| 465 // Provide a time function that does nothing (runs fast) when we don't have | 547 // Provide a time function that does nothing (runs fast) when we don't have |
| (...skipping 20 matching lines...) Expand all Loading... |
| 486 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a | 568 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a |
| 487 // better change of optimizing (inlining? etc.) private methods (knowing that | 569 // better change of optimizing (inlining? etc.) private methods (knowing that |
| 488 // there will be no need for an external entry point). | 570 // there will be no need for an external entry point). |
| 489 friend class TrackedObjectsTest; | 571 friend class TrackedObjectsTest; |
| 490 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); | 572 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); |
| 491 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); | 573 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); |
| 492 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); | 574 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); |
| 493 | 575 |
| 494 typedef std::map<const BirthOnThread*, int> BirthCountMap; | 576 typedef std::map<const BirthOnThread*, int> BirthCountMap; |
| 495 | 577 |
| 578 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> |
| 579 DeathsSnapshot; |
| 580 |
| 496 // Worker thread construction creates a name since there is none. | 581 // Worker thread construction creates a name since there is none. |
| 497 explicit ThreadData(int thread_number); | 582 explicit ThreadData(int thread_number); |
| 498 | 583 |
| 499 // Message loop based construction should provide a name. | 584 // Message loop based construction should provide a name. |
| 500 explicit ThreadData(const std::string& suggested_name); | 585 explicit ThreadData(const std::string& suggested_name); |
| 501 | 586 |
| 502 ~ThreadData(); | 587 ~ThreadData(); |
| 503 | 588 |
| 504 // Push this instance to the head of all_thread_data_list_head_, linking it to | 589 // Push this instance to the head of all_thread_data_list_head_, linking it to |
| 505 // the previous head. This is performed after each construction, and leaves | 590 // the previous head. This is performed after each construction, and leaves |
| 506 // the instance permanently on that list. | 591 // the instance permanently on that list. |
| 507 void PushToHeadOfList(); | 592 void PushToHeadOfList(); |
| 508 | 593 |
| 509 // (Thread safe) Get start of list of all ThreadData instances using the lock. | 594 // (Thread safe) Get start of list of all ThreadData instances using the lock. |
| 510 static ThreadData* first(); | 595 static ThreadData* first(); |
| 511 | 596 |
| 512 // Iterate through the null terminated list of ThreadData instances. | 597 // Iterate through the null terminated list of ThreadData instances. |
| 513 ThreadData* next() const; | 598 ThreadData* next() const; |
| 514 | 599 |
| 515 | 600 |
| 516 // In this thread's data, record a new birth. | 601 // In this thread's data, record a new birth. |
| 517 Births* TallyABirth(const Location& location); | 602 Births* TallyABirth(const Location& location); |
| 518 | 603 |
| 519 // Find a place to record a death on this thread. | 604 // Find a place to record a death on this thread. |
| 520 void TallyADeath(const Births& birth, | 605 void TallyADeath(const Births& births, |
| 521 int32 queue_duration, | 606 int32 queue_duration, |
| 522 const TaskStopwatch& stopwatch); | 607 const TaskStopwatch& stopwatch); |
| 523 | 608 |
| 524 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData | |
| 525 // instance. Also updates the |birth_counts| tally for each task to keep | |
| 526 // track of the number of living instances of the task. | |
| 527 static void SnapshotAllExecutedTasks( | |
| 528 ProcessDataPhaseSnapshot* process_data_phase, | |
| 529 BirthCountMap* birth_counts); | |
| 530 | |
| 531 // Fills |process_data_phase| with all the recursive results in our process. | |
| 532 static void SnapshotCurrentPhase( | |
| 533 ProcessDataPhaseSnapshot* process_data_phase); | |
| 534 | |
| 535 // Snapshots (under a lock) the profiled data for the tasks for this thread | 609 // Snapshots (under a lock) the profiled data for the tasks for this thread |
| 536 // and writes all of the executed tasks' data -- i.e. the data for the tasks | 610 // and writes all of the executed tasks' data -- i.e. the data for all |
| 537 // with with entries in the death_map_ -- into |process_data_phase|. Also | 611 // profiling phases (including the current one: |current_profiling_phase|) for |
| 538 // updates the |birth_counts| tally for each task to keep track of the number | 612 // the tasks with with entries in the death_map_ -- into |phased_snapshots|. |
| 539 // of living instances of the task -- that is, each task maps to the number of | 613 // Also updates the |birth_counts| tally for each task to keep track of the |
| 540 // births for the task that have not yet been balanced by a death. | 614 // number of living instances of the task -- that is, each task maps to the |
| 541 void SnapshotExecutedTasks(ProcessDataPhaseSnapshot* process_data_phase, | 615 // number of births for the task that have not yet been balanced by a death. |
| 616 void SnapshotExecutedTasks(int current_profiling_phase, |
| 617 PhasedProcessDataSnapshotMap* phased_snapshots, |
| 542 BirthCountMap* birth_counts); | 618 BirthCountMap* birth_counts); |
| 543 | 619 |
| 544 // Using our lock, make a copy of the specified maps. This call may be made | 620 // Using our lock, make a copy of the specified maps. This call may be made |
| 545 // on non-local threads, which necessitate the use of the lock to prevent | 621 // on non-local threads, which necessitate the use of the lock to prevent |
| 546 // the map(s) from being reallocated while they are copied. | 622 // the map(s) from being reallocated while they are copied. |
| 547 void SnapshotMaps(BirthMap* birth_map, | 623 void SnapshotMaps(int profiling_phase, |
| 548 DeathMap* death_map, | 624 BirthMap* birth_map, |
| 625 DeathsSnapshot* deaths, |
| 549 ParentChildSet* parent_child_set); | 626 ParentChildSet* parent_child_set); |
| 550 | 627 |
| 628 // Called for this thread when the current profiling phase, identified by |
| 629 // |profiling_phase|, ends. |
| 630 void OnProfilingPhaseCompletedOnThread(int profiling_phase); |
| 631 |
| 551 // This method is called by the TLS system when a thread terminates. | 632 // This method is called by the TLS system when a thread terminates. |
| 552 // The argument may be NULL if this thread has never tracked a birth or death. | 633 // The argument may be NULL if this thread has never tracked a birth or death. |
| 553 static void OnThreadTermination(void* thread_data); | 634 static void OnThreadTermination(void* thread_data); |
| 554 | 635 |
| 555 // This method should be called when a worker thread terminates, so that we | 636 // This method should be called when a worker thread terminates, so that we |
| 556 // can save all the thread data into a cache of reusable ThreadData instances. | 637 // can save all the thread data into a cache of reusable ThreadData instances. |
| 557 void OnThreadTerminationCleanup(); | 638 void OnThreadTerminationCleanup(); |
| 558 | 639 |
| 559 // Cleans up data structures, and returns statics to near pristine (mostly | 640 // Cleans up data structures, and returns statics to near pristine (mostly |
| 560 // uninitialized) state. If there is any chance that other threads are still | 641 // uninitialized) state. If there is any chance that other threads are still |
| (...skipping 10 matching lines...) Expand all Loading... |
| 571 // increasing time functcion. | 652 // increasing time functcion. |
| 572 static NowFunction* now_function_; | 653 static NowFunction* now_function_; |
| 573 | 654 |
| 574 // If true, now_function_ returns values that can be used to calculate queue | 655 // If true, now_function_ returns values that can be used to calculate queue |
| 575 // time. | 656 // time. |
| 576 static bool now_function_is_time_; | 657 static bool now_function_is_time_; |
| 577 | 658 |
| 578 // We use thread local store to identify which ThreadData to interact with. | 659 // We use thread local store to identify which ThreadData to interact with. |
| 579 static base::ThreadLocalStorage::StaticSlot tls_index_; | 660 static base::ThreadLocalStorage::StaticSlot tls_index_; |
| 580 | 661 |
| 581 // List of ThreadData instances for use with worker threads. When a worker | 662 // List of ThreadData instances for use with worker threads. When a worker |
| 582 // thread is done (terminated), we push it onto this list. When a new worker | 663 // thread is done (terminated), we push it onto this list. When a new worker |
| 583 // thread is created, we first try to re-use a ThreadData instance from the | 664 // thread is created, we first try to re-use a ThreadData instance from the |
| 584 // list, and if none are available, construct a new one. | 665 // list, and if none are available, construct a new one. |
| 585 // This is only accessed while list_lock_ is held. | 666 // This is only accessed while list_lock_ is held. |
| 586 static ThreadData* first_retired_worker_; | 667 static ThreadData* first_retired_worker_; |
| 587 | 668 |
| 588 // Link to the most recently created instance (starts a null terminated list). | 669 // Link to the most recently created instance (starts a null terminated list). |
| 589 // The list is traversed by about:profiler when it needs to snapshot data. | 670 // The list is traversed by about:profiler when it needs to snapshot data. |
| 590 // This is only accessed while list_lock_ is held. | 671 // This is only accessed while list_lock_ is held. |
| 591 static ThreadData* all_thread_data_list_head_; | 672 static ThreadData* all_thread_data_list_head_; |
| 592 | 673 |
| 593 // The next available worker thread number. This should only be accessed when | 674 // The next available worker thread number. This should only be accessed when |
| 594 // the list_lock_ is held. | 675 // the list_lock_ is held. |
| 595 static int worker_thread_data_creation_count_; | 676 static int worker_thread_data_creation_count_; |
| 596 | 677 |
| 597 // The number of times TLS has called us back to cleanup a ThreadData | 678 // The number of times TLS has called us back to cleanup a ThreadData |
| 598 // instance. This is only accessed while list_lock_ is held. | 679 // instance. This is only accessed while list_lock_ is held. |
| 599 static int cleanup_count_; | 680 static int cleanup_count_; |
| 600 | 681 |
| 601 // Incarnation sequence number, indicating how many times (during unittests) | 682 // Incarnation sequence number, indicating how many times (during unittests) |
| 602 // we've either transitioned out of UNINITIALIZED, or into that state. This | 683 // we've either transitioned out of UNINITIALIZED, or into that state. This |
| 603 // value is only accessed while the list_lock_ is held. | 684 // value is only accessed while the list_lock_ is held. |
| 604 static int incarnation_counter_; | 685 static int incarnation_counter_; |
| 605 | 686 |
| 606 // Protection for access to all_thread_data_list_head_, and to | 687 // Protection for access to all_thread_data_list_head_, and to |
| 607 // unregistered_thread_data_pool_. This lock is leaked at shutdown. | 688 // unregistered_thread_data_pool_. This lock is leaked at shutdown. |
| 608 // The lock is very infrequently used, so we can afford to just make a lazy | 689 // The lock is very infrequently used, so we can afford to just make a lazy |
| 609 // instance and be safe. | 690 // instance and be safe. |
| 610 static base::LazyInstance<base::Lock>::Leaky list_lock_; | 691 static base::LazyInstance<base::Lock>::Leaky list_lock_; |
| 611 | 692 |
| 612 // We set status_ to SHUTDOWN when we shut down the tracking service. | 693 // We set status_ to SHUTDOWN when we shut down the tracking service. |
| 613 static Status status_; | 694 static Status status_; |
| 614 | 695 |
| 615 // Link to next instance (null terminated list). Used to globally track all | 696 // Link to next instance (null terminated list). Used to globally track all |
| 616 // registered instances (corresponds to all registered threads where we keep | 697 // registered instances (corresponds to all registered threads where we keep |
| 617 // data). | 698 // data). |
| 618 ThreadData* next_; | 699 ThreadData* next_; |
| 619 | 700 |
| 620 // Pointer to another ThreadData instance for a Worker-Thread that has been | 701 // Pointer to another ThreadData instance for a Worker-Thread that has been |
| 621 // retired (its thread was terminated). This value is non-NULL only for a | 702 // retired (its thread was terminated). This value is non-NULL only for a |
| 622 // retired ThreadData associated with a Worker-Thread. | 703 // retired ThreadData associated with a Worker-Thread. |
| 623 ThreadData* next_retired_worker_; | 704 ThreadData* next_retired_worker_; |
| 624 | 705 |
| 625 // The name of the thread that is being recorded. If this thread has no | 706 // The name of the thread that is being recorded. If this thread has no |
| (...skipping 11 matching lines...) Expand all Loading... |
| 637 // When a snapshot is needed, this structure can be locked in place for the | 718 // When a snapshot is needed, this structure can be locked in place for the |
| 638 // duration of the snapshotting activity. | 719 // duration of the snapshotting activity. |
| 639 BirthMap birth_map_; | 720 BirthMap birth_map_; |
| 640 | 721 |
| 641 // Similar to birth_map_, this records informations about death of tracked | 722 // Similar to birth_map_, this records informations about death of tracked |
| 642 // instances (i.e., when a tracked instance was destroyed on this thread). | 723 // instances (i.e., when a tracked instance was destroyed on this thread). |
| 643 // It is locked before changing, and hence other threads may access it by | 724 // It is locked before changing, and hence other threads may access it by |
| 644 // locking before reading it. | 725 // locking before reading it. |
| 645 DeathMap death_map_; | 726 DeathMap death_map_; |
| 646 | 727 |
| 647 // A set of parents that created children tasks on this thread. Each pair | 728 // A set of parents that created children tasks on this thread. Each pair |
| 648 // corresponds to potentially non-local Births (location and thread), and a | 729 // corresponds to potentially non-local Births (location and thread), and a |
| 649 // local Births (that took place on this thread). | 730 // local Births (that took place on this thread). |
| 650 ParentChildSet parent_child_set_; | 731 ParentChildSet parent_child_set_; |
| 651 | 732 |
| 652 // Lock to protect *some* access to BirthMap and DeathMap. The maps are | 733 // Lock to protect *some* access to BirthMap and DeathMap. The maps are |
| 653 // regularly read and written on this thread, but may only be read from other | 734 // regularly read and written on this thread, but may only be read from other |
| 654 // threads. To support this, we acquire this lock if we are writing from this | 735 // threads. To support this, we acquire this lock if we are writing from this |
| 655 // thread, or reading from another thread. For reading from this thread we | 736 // thread, or reading from another thread. For reading from this thread we |
| 656 // don't need a lock, as there is no potential for a conflict since the | 737 // don't need a lock, as there is no potential for a conflict since the |
| 657 // writing is only done from this thread. | 738 // writing is only done from this thread. |
| 658 mutable base::Lock map_lock_; | 739 mutable base::Lock map_lock_; |
| 659 | 740 |
| 660 // The stack of parents that are currently being profiled. This includes only | 741 // The stack of parents that are currently being profiled. This includes only |
| 661 // tasks that have started a timer recently via PrepareForStartOfRun(), but | 742 // tasks that have started a timer recently via PrepareForStartOfRun(), but |
| 662 // not yet concluded with a NowForEndOfRun(). Usually this stack is one deep, | 743 // not yet concluded with a NowForEndOfRun(). Usually this stack is one deep, |
| 663 // but if a scoped region is profiled, or <sigh> a task runs a nested-message | 744 // but if a scoped region is profiled, or <sigh> a task runs a nested-message |
| 664 // loop, then the stack can grow larger. Note that we don't try to deduct | 745 // loop, then the stack can grow larger. Note that we don't try to deduct |
| 665 // time in nested profiles, as our current timer is based on wall-clock time, | 746 // time in nested profiles, as our current timer is based on wall-clock time, |
| 666 // and not CPU time (and we're hopeful that nested timing won't be a | 747 // and not CPU time (and we're hopeful that nested timing won't be a |
| 667 // significant additional cost). | 748 // significant additional cost). |
| 668 ParentStack parent_stack_; | 749 ParentStack parent_stack_; |
| 669 | 750 |
| 670 // A random number that we used to select decide which sample to keep as a | 751 // A random number that we used to select decide which sample to keep as a |
| (...skipping 10 matching lines...) Expand all Loading... |
| 681 | 762 |
| 682 // Most recently started (i.e. most nested) stopwatch on the current thread, | 763 // Most recently started (i.e. most nested) stopwatch on the current thread, |
| 683 // if it exists; NULL otherwise. | 764 // if it exists; NULL otherwise. |
| 684 TaskStopwatch* current_stopwatch_; | 765 TaskStopwatch* current_stopwatch_; |
| 685 | 766 |
| 686 DISALLOW_COPY_AND_ASSIGN(ThreadData); | 767 DISALLOW_COPY_AND_ASSIGN(ThreadData); |
| 687 }; | 768 }; |
| 688 | 769 |
| 689 //------------------------------------------------------------------------------ | 770 //------------------------------------------------------------------------------ |
| 690 // Stopwatch to measure task run time or simply create a time interval that will | 771 // Stopwatch to measure task run time or simply create a time interval that will |
| 691 // be subtracted from the current most nested task's run time. Stopwatches | 772 // be subtracted from the current most nested task's run time. Stopwatches |
| 692 // coordinate with the stopwatches in which they are nested to avoid | 773 // coordinate with the stopwatches in which they are nested to avoid |
| 693 // double-counting nested tasks run times. | 774 // double-counting nested tasks run times. |
| 694 | 775 |
| 695 class BASE_EXPORT TaskStopwatch { | 776 class BASE_EXPORT TaskStopwatch { |
| 696 public: | 777 public: |
| 697 // Starts the stopwatch. | 778 // Starts the stopwatch. |
| 698 TaskStopwatch(); | 779 TaskStopwatch(); |
| 699 ~TaskStopwatch(); | 780 ~TaskStopwatch(); |
| 700 | 781 |
| 701 // Starts stopwatch. | 782 // Starts stopwatch. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 729 // Sum of wallclock durations of all stopwatches that were directly nested in | 810 // Sum of wallclock durations of all stopwatches that were directly nested in |
| 730 // this one. | 811 // this one. |
| 731 int32 excluded_duration_ms_; | 812 int32 excluded_duration_ms_; |
| 732 | 813 |
| 733 // Stopwatch which was running on our thread when this stopwatch was started. | 814 // Stopwatch which was running on our thread when this stopwatch was started. |
| 734 // That preexisting stopwatch must be adjusted to the exclude the wallclock | 815 // That preexisting stopwatch must be adjusted to the exclude the wallclock |
| 735 // duration of this stopwatch. | 816 // duration of this stopwatch. |
| 736 TaskStopwatch* parent_; | 817 TaskStopwatch* parent_; |
| 737 | 818 |
| 738 #if DCHECK_IS_ON() | 819 #if DCHECK_IS_ON() |
| 739 // State of the stopwatch. Stopwatch is first constructed in a created state | 820 // State of the stopwatch. Stopwatch is first constructed in a created state |
| 740 // state, then is optionally started/stopped, then destructed. | 821 // state, then is optionally started/stopped, then destructed. |
| 741 enum { CREATED, RUNNING, STOPPED } state_; | 822 enum { CREATED, RUNNING, STOPPED } state_; |
| 742 | 823 |
| 743 // Currently running stopwatch that is directly nested in this one, if such | 824 // Currently running stopwatch that is directly nested in this one, if such |
| 744 // stopwatch exists. NULL otherwise. | 825 // stopwatch exists. NULL otherwise. |
| 745 TaskStopwatch* child_; | 826 TaskStopwatch* child_; |
| 746 #endif | 827 #endif |
| 747 }; | 828 }; |
| 748 | 829 |
| 749 //------------------------------------------------------------------------------ | 830 //------------------------------------------------------------------------------ |
| 750 // A snapshotted representation of a (parent, child) task pair, for tracking | 831 // A snapshotted representation of a (parent, child) task pair, for tracking |
| 751 // hierarchical profiles. | 832 // hierarchical profiles. |
| 752 | 833 |
| 753 struct BASE_EXPORT ParentChildPairSnapshot { | 834 struct BASE_EXPORT ParentChildPairSnapshot { |
| 754 public: | 835 public: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 776 | 857 |
| 777 //------------------------------------------------------------------------------ | 858 //------------------------------------------------------------------------------ |
| 778 // A snapshotted representation of the list of ThreadData objects for a process, | 859 // A snapshotted representation of the list of ThreadData objects for a process, |
| 779 // for all profiling phases, including the current one. | 860 // for all profiling phases, including the current one. |
| 780 | 861 |
| 781 struct BASE_EXPORT ProcessDataSnapshot { | 862 struct BASE_EXPORT ProcessDataSnapshot { |
| 782 public: | 863 public: |
| 783 ProcessDataSnapshot(); | 864 ProcessDataSnapshot(); |
| 784 ~ProcessDataSnapshot(); | 865 ~ProcessDataSnapshot(); |
| 785 | 866 |
| 786 PhasedProcessDataSnapshotMap phased_process_data_snapshots; | 867 PhasedProcessDataSnapshotMap phased_snapshots; |
| 787 base::ProcessId process_id; | 868 base::ProcessId process_id; |
| 788 }; | 869 }; |
| 789 | 870 |
| 790 } // namespace tracked_objects | 871 } // namespace tracked_objects |
| 791 | 872 |
| 792 #endif // BASE_TRACKED_OBJECTS_H_ | 873 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |