| 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 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <stack> | 11 #include <stack> |
| 12 #include <string> | 12 #include <string> |
| 13 #include <utility> | 13 #include <utility> |
| 14 #include <vector> | 14 #include <vector> |
| 15 | 15 |
| 16 #include "base/base_export.h" | 16 #include "base/base_export.h" |
| 17 #include "base/gtest_prod_util.h" | 17 #include "base/gtest_prod_util.h" |
| 18 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
| 19 #include "base/location.h" | 19 #include "base/location.h" |
| 20 #include "base/profiler/alternate_timer.h" | 20 #include "base/profiler/alternate_timer.h" |
| 21 #include "base/profiler/tracked_time.h" | 21 #include "base/profiler/tracked_time.h" |
| 22 #include "base/time.h" | 22 #include "base/time.h" |
| 23 #include "base/synchronization/lock.h" | 23 #include "base/synchronization/lock.h" |
| 24 #include "base/threading/thread_local_storage.h" | 24 #include "base/threading/thread_local_storage.h" |
| 25 #include "base/tracking_info.h" | 25 #include "base/tracking_info.h" |
| 26 // TODO(isherman): Remove this include, and fixup downstream files that depend |
| 27 // on it. |
| 26 #include "base/values.h" | 28 #include "base/values.h" |
| 27 | 29 |
| 30 namespace base { |
| 31 class DictionaryValue; |
| 32 } |
| 33 |
| 28 // TrackedObjects provides a database of stats about objects (generally Tasks) | 34 // TrackedObjects provides a database of stats about objects (generally Tasks) |
| 29 // that are tracked. Tracking means their birth, death, duration, birth thread, | 35 // that are tracked. Tracking means their birth, death, duration, birth thread, |
| 30 // death thread, and birth place are recorded. This data is carefully spread | 36 // death thread, and birth place are recorded. This data is carefully spread |
| 31 // across a series of objects so that the counts and times can be rapidly | 37 // across a series of objects so that the counts and times can be rapidly |
| 32 // updated without (usually) having to lock the data, and hence there is usually | 38 // updated without (usually) having to lock the data, and hence there is usually |
| 33 // very little contention caused by the tracking. The data can be viewed via | 39 // very little contention caused by the tracking. The data can be viewed via |
| 34 // the about:profiler URL, with a variety of sorting and filtering choices. | 40 // the about:profiler URL, with a variety of sorting and filtering choices. |
| 35 // | 41 // |
| 36 // These classes serve as the basis of a profiler of sorts for the Tasks system. | 42 // These classes serve as the basis of a profiler of sorts for the Tasks system. |
| 37 // As a result, design decisions were made to maximize speed, by minimizing | 43 // As a result, design decisions were made to maximize speed, by minimizing |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 // very little global performance impact. | 128 // very little global performance impact. |
| 123 // | 129 // |
| 124 // The above description tries to define the high performance (run time) | 130 // The above description tries to define the high performance (run time) |
| 125 // portions of these classes. After gathering statistics, calls instigated | 131 // portions of these classes. After gathering statistics, calls instigated |
| 126 // by visiting about:profiler will assemble and aggregate data for display. The | 132 // by visiting about:profiler will assemble and aggregate data for display. The |
| 127 // following data structures are used for producing such displays. They are | 133 // following data structures are used for producing such displays. They are |
| 128 // not performance critical, and their only major constraint is that they should | 134 // not performance critical, and their only major constraint is that they should |
| 129 // be able to run concurrently with ongoing augmentation of the birth and death | 135 // be able to run concurrently with ongoing augmentation of the birth and death |
| 130 // data. | 136 // data. |
| 131 // | 137 // |
| 138 // This header also exports collection of classes that provide serialized |
| 139 // representations of the core tracked_objects:: classes. These serialized |
| 140 // representations are designed for safe transmission of the tracked_objects:: |
| 141 // data across process boundaries. Each consists of: |
| 142 // (1) a default constructor, to support the IPC serialization macros, |
| 143 // (2) a simple constructor that extracts data from the type being serialized, |
| 144 // (3) a ToValue() function that writes the serialized data into the passed |
| 145 // |dictionary| -- which will typically then be automatically translated to |
| 146 // JSON for rendering the collected profiler data -- and |
| 147 // (4) the serialized data. |
| 148 // |
| 132 // For a given birth location, information about births is spread across data | 149 // For a given birth location, information about births is spread across data |
| 133 // structures that are asynchronously changing on various threads. For display | 150 // structures that are asynchronously changing on various threads. For |
| 134 // purposes, we need to construct Snapshot instances for each combination of | 151 // serialization and display purposes, we need to construct SerializedSnapshot |
| 135 // birth thread, death thread, and location, along with the count of such | 152 // instances for each combination of birth thread, death thread, and location, |
| 136 // lifetimes. We gather such data into a Snapshot instances, so that such | 153 // along with the count of such lifetimes. We gather such data into a |
| 137 // instances can be sorted and aggregated (and remain frozen during our | 154 // SerializedSnapshot instances, so that such instances can be sorted and |
| 138 // processing). Snapshot instances use pointers to constant portions of the | 155 // aggregated (and remain frozen during our processing). |
| 139 // birth and death datastructures, but have local (frozen) copies of the actual | |
| 140 // statistics (birth count, durations, etc. etc.). | |
| 141 // | 156 // |
| 142 // A DataCollector is a container object that holds a set of Snapshots. The | 157 // The SerializedProcessData struct is a serialized representation of the list |
| 143 // statistics in a snapshot are gathered asynhcronously relative to their | 158 // of ThreadData objects for a process. It holds a set of SerializedSnapshots |
| 144 // ongoing updates. It is possible, though highly unlikely, that stats could be | 159 // and tracks parent/child relationships for the executed tasks. The statistics |
| 145 // incorrectly recorded by this process (all data is held in 32 bit ints, but we | 160 // in a snapshot are gathered asynhcronously relative to their ongoing updates. |
| 146 // are not atomically collecting all data, so we could have count that does not, | 161 // It is possible, though highly unlikely, that stats could be incorrectly |
| 147 // for example, match with the number of durations we accumulated). The | 162 // recorded by this process (all data is held in 32 bit ints, but we are not |
| 148 // advantage to having fast (non-atomic) updates of the data outweighs the | 163 // atomically collecting all data, so we could have count that does not, for |
| 149 // minimal risk of a singular corrupt statistic snapshot (only the snapshot | 164 // example, match with the number of durations we accumulated). The advantage |
| 150 // could be corrupt, not the underlying and ongoing statistic). In constrast, | 165 // to having fast (non-atomic) updates of the data outweighs the minimal risk of |
| 151 // pointer data that is accessed during snapshotting is completely invariant, | 166 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, |
| 152 // and hence is perfectly acquired (i.e., no potential corruption, and no risk | 167 // not the underlying and ongoing statistic). In constrast, pointer data that |
| 153 // of a bad memory reference). | 168 // is accessed during snapshotting is completely invariant, and hence is |
| 154 // | 169 // perfectly acquired (i.e., no potential corruption, and no risk of a bad |
| 155 // After an array of Snapshots instances are collected into a DataCollector, | 170 // memory reference). |
| 156 // they need to be prepared for displaying our output. We currently implement a | |
| 157 // serialization into a Value hierarchy, which is automatically translated to | |
| 158 // JSON when supplied to rendering Java Scirpt. | |
| 159 // | 171 // |
| 160 // TODO(jar): We can implement a Snapshot system that *tries* to grab the | 172 // TODO(jar): We can implement a Snapshot system that *tries* to grab the |
| 161 // snapshots on the source threads *when* they have MessageLoops available | 173 // snapshots on the source threads *when* they have MessageLoops available |
| 162 // (worker threads don't have message loops generally, and hence gathering from | 174 // (worker threads don't have message loops generally, and hence gathering from |
| 163 // them will continue to be asynchronous). We had an implementation of this in | 175 // them will continue to be asynchronous). We had an implementation of this in |
| 164 // the past, but the difficulty is dealing with message loops being terminated. | 176 // the past, but the difficulty is dealing with message loops being terminated. |
| 165 // We can *try* to spam the available threads via some message loop proxy to | 177 // We can *try* to spam the available threads via some message loop proxy to |
| 166 // achieve this feat, and it *might* be valuable when we are colecting data for | 178 // achieve this feat, and it *might* be valuable when we are colecting data for |
| 167 // upload via UMA (where correctness of data may be more significant than for a | 179 // upload via UMA (where correctness of data may be more significant than for a |
| 168 // single screen of about:profiler). | 180 // single screen of about:profiler). |
| (...skipping 20 matching lines...) Expand all Loading... |
| 189 namespace tracked_objects { | 201 namespace tracked_objects { |
| 190 | 202 |
| 191 //------------------------------------------------------------------------------ | 203 //------------------------------------------------------------------------------ |
| 192 // For a specific thread, and a specific birth place, the collection of all | 204 // For a specific thread, and a specific birth place, the collection of all |
| 193 // death info (with tallies for each death thread, to prevent access conflicts). | 205 // death info (with tallies for each death thread, to prevent access conflicts). |
| 194 class ThreadData; | 206 class ThreadData; |
| 195 class BASE_EXPORT BirthOnThread { | 207 class BASE_EXPORT BirthOnThread { |
| 196 public: | 208 public: |
| 197 BirthOnThread(const Location& location, const ThreadData& current); | 209 BirthOnThread(const Location& location, const ThreadData& current); |
| 198 | 210 |
| 199 const Location location() const; | 211 const Location location() const { return location_; } |
| 200 const ThreadData* birth_thread() const; | 212 const ThreadData* birth_thread() const { return birth_thread_; } |
| 201 | |
| 202 // Insert our state (location, and thread name) into the dictionary. | |
| 203 // Use the supplied |prefix| in front of "thread_name" and "location" | |
| 204 // respectively when defining keys. | |
| 205 void ToValue(const std::string& prefix, | |
| 206 base::DictionaryValue* dictionary) const; | |
| 207 | 213 |
| 208 private: | 214 private: |
| 209 // File/lineno of birth. This defines the essence of the task, as the context | 215 // File/lineno of birth. This defines the essence of the task, as the context |
| 210 // of the birth (construction) often tell what the item is for. This field | 216 // of the birth (construction) often tell what the item is for. This field |
| 211 // is const, and hence safe to access from any thread. | 217 // is const, and hence safe to access from any thread. |
| 212 const Location location_; | 218 const Location location_; |
| 213 | 219 |
| 214 // The thread that records births into this object. Only this thread is | 220 // The thread that records births into this object. Only this thread is |
| 215 // allowed to update birth_count_ (which changes over time). | 221 // allowed to update birth_count_ (which changes over time). |
| 216 const ThreadData* const birth_thread_; | 222 const ThreadData* const birth_thread_; |
| 217 | 223 |
| 218 DISALLOW_COPY_AND_ASSIGN(BirthOnThread); | 224 DISALLOW_COPY_AND_ASSIGN(BirthOnThread); |
| 219 }; | 225 }; |
| 220 | 226 |
| 221 //------------------------------------------------------------------------------ | 227 //------------------------------------------------------------------------------ |
| 228 // A serialized representation of the BirthOnThread class. |
| 229 |
| 230 struct BASE_EXPORT SerializedBirthOnThread { |
| 231 SerializedBirthOnThread(); |
| 232 SerializedBirthOnThread(const BirthOnThread& birth); |
| 233 ~SerializedBirthOnThread(); |
| 234 |
| 235 // Insert our state (location, and thread name) into the dictionary. Use the |
| 236 // supplied |prefix| in front of "thread" and "location" when defining keys. |
| 237 void ToValue(const std::string& prefix, |
| 238 base::DictionaryValue* dictionary) const; |
| 239 |
| 240 SerializedLocation location; |
| 241 std::string thread_name; |
| 242 }; |
| 243 |
| 244 //------------------------------------------------------------------------------ |
| 222 // A class for accumulating counts of births (without bothering with a map<>). | 245 // A class for accumulating counts of births (without bothering with a map<>). |
| 223 | 246 |
| 224 class BASE_EXPORT Births: public BirthOnThread { | 247 class BASE_EXPORT Births: public BirthOnThread { |
| 225 public: | 248 public: |
| 226 Births(const Location& location, const ThreadData& current); | 249 Births(const Location& location, const ThreadData& current); |
| 227 | 250 |
| 228 int birth_count() const; | 251 int birth_count() const; |
| 229 | 252 |
| 230 // When we have a birth we update the count for this BirhPLace. | 253 // When we have a birth we update the count for this birthplace. |
| 231 void RecordBirth(); | 254 void RecordBirth(); |
| 232 | 255 |
| 233 // When a birthplace is changed (updated), we need to decrement the counter | 256 // When a birthplace is changed (updated), we need to decrement the counter |
| 234 // for the old instance. | 257 // for the old instance. |
| 235 void ForgetBirth(); | 258 void ForgetBirth(); |
| 236 | 259 |
| 237 // Hack to quickly reset all counts to zero. | 260 // Hack to quickly reset all counts to zero. |
| 238 void Clear(); | 261 void Clear(); |
| 239 | 262 |
| 240 private: | 263 private: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 258 // threads, we create DeathData stats that tally the number of births without | 281 // threads, we create DeathData stats that tally the number of births without |
| 259 // a corresponding death. | 282 // a corresponding death. |
| 260 explicit DeathData(int count); | 283 explicit DeathData(int count); |
| 261 | 284 |
| 262 // Update stats for a task destruction (death) that had a Run() time of | 285 // Update stats for a task destruction (death) that had a Run() time of |
| 263 // |duration|, and has had a queueing delay of |queue_duration|. | 286 // |duration|, and has had a queueing delay of |queue_duration|. |
| 264 void RecordDeath(const DurationInt queue_duration, | 287 void RecordDeath(const DurationInt queue_duration, |
| 265 const DurationInt run_duration, | 288 const DurationInt run_duration, |
| 266 int random_number); | 289 int random_number); |
| 267 | 290 |
| 268 // Metrics accessors, used only in tests. | 291 // Metrics accessors, used only for serialization and in tests. |
| 269 int count() const; | 292 int count() const; |
| 270 DurationInt run_duration_sum() const; | 293 DurationInt run_duration_sum() const; |
| 271 DurationInt run_duration_max() const; | 294 DurationInt run_duration_max() const; |
| 272 DurationInt run_duration_sample() const; | 295 DurationInt run_duration_sample() const; |
| 273 DurationInt queue_duration_sum() const; | 296 DurationInt queue_duration_sum() const; |
| 274 DurationInt queue_duration_max() const; | 297 DurationInt queue_duration_max() const; |
| 275 DurationInt queue_duration_sample() const; | 298 DurationInt queue_duration_sample() const; |
| 276 | 299 |
| 277 // Construct a DictionaryValue instance containing all our stats. The caller | |
| 278 // assumes ownership of the returned instance. | |
| 279 base::DictionaryValue* ToValue() const; | |
| 280 | |
| 281 // Reset the max values to zero. | 300 // Reset the max values to zero. |
| 282 void ResetMax(); | 301 void ResetMax(); |
| 283 | 302 |
| 284 // Reset all tallies to zero. This is used as a hack on realtime data. | 303 // Reset all tallies to zero. This is used as a hack on realtime data. |
| 285 void Clear(); | 304 void Clear(); |
| 286 | 305 |
| 287 private: | 306 private: |
| 288 // Members are ordered from most regularly read and updated, to least | 307 // Members are ordered from most regularly read and updated, to least |
| 289 // frequently used. This might help a bit with cache lines. | 308 // frequently used. This might help a bit with cache lines. |
| 290 // Number of runs seen (divisor for calculating averages). | 309 // Number of runs seen (divisor for calculating averages). |
| 291 int count_; | 310 int count_; |
| 292 // Basic tallies, used to compute averages. | 311 // Basic tallies, used to compute averages. |
| 293 DurationInt run_duration_sum_; | 312 DurationInt run_duration_sum_; |
| 294 DurationInt queue_duration_sum_; | 313 DurationInt queue_duration_sum_; |
| 295 // Max values, used by local visualization routines. These are often read, | 314 // Max values, used by local visualization routines. These are often read, |
| 296 // but rarely updated. | 315 // but rarely updated. |
| 297 DurationInt run_duration_max_; | 316 DurationInt run_duration_max_; |
| 298 DurationInt queue_duration_max_; | 317 DurationInt queue_duration_max_; |
| 299 // Samples, used by by crowd sourcing gatherers. These are almost never read, | 318 // Samples, used by crowd sourcing gatherers. These are almost never read, |
| 300 // and rarely updated. | 319 // and rarely updated. |
| 301 DurationInt run_duration_sample_; | 320 DurationInt run_duration_sample_; |
| 302 DurationInt queue_duration_sample_; | 321 DurationInt queue_duration_sample_; |
| 303 }; | 322 }; |
| 304 | 323 |
| 305 //------------------------------------------------------------------------------ | 324 //------------------------------------------------------------------------------ |
| 325 // A serialized representation of the DeathData class. |
| 326 |
| 327 struct BASE_EXPORT SerializedDeathData { |
| 328 SerializedDeathData(); |
| 329 SerializedDeathData(const DeathData& death_data); |
| 330 ~SerializedDeathData(); |
| 331 |
| 332 void ToValue(base::DictionaryValue* dictionary) const; |
| 333 |
| 334 int count; |
| 335 DurationInt run_duration_sum; |
| 336 DurationInt run_duration_max; |
| 337 DurationInt run_duration_sample; |
| 338 DurationInt queue_duration_sum; |
| 339 DurationInt queue_duration_max; |
| 340 DurationInt queue_duration_sample; |
| 341 }; |
| 342 |
| 343 //------------------------------------------------------------------------------ |
| 306 // A temporary collection of data that can be sorted and summarized. It is | 344 // A temporary collection of data that can be sorted and summarized. It is |
| 307 // gathered (carefully) from many threads. Instances are held in arrays and | 345 // gathered (carefully) from many threads. Instances are held in arrays and |
| 308 // processed, filtered, and rendered. | 346 // processed, filtered, and rendered. |
| 309 // The source of this data was collected on many threads, and is asynchronously | 347 // The source of this data was collected on many threads, and is asynchronously |
| 310 // changing. The data in this instance is not asynchronously changing. | 348 // changing. The data in this instance is not asynchronously changing. |
| 311 | 349 |
| 312 class BASE_EXPORT Snapshot { | 350 struct BASE_EXPORT SerializedSnapshot { |
| 313 public: | 351 SerializedSnapshot(); |
| 314 // When snapshotting a full life cycle set (birth-to-death), use this: | 352 SerializedSnapshot(const BirthOnThread& birth, |
| 315 Snapshot(const BirthOnThread& birth_on_thread, | 353 const DeathData& death_data, |
| 316 const ThreadData& death_thread, | 354 const std::string& death_thread_name); |
| 317 const DeathData& death_data); | 355 ~SerializedSnapshot(); |
| 318 | 356 |
| 319 // When snapshotting a birth, with no death yet, use this: | 357 void ToValue(base::DictionaryValue* dictionary) const; |
| 320 Snapshot(const BirthOnThread& birth_on_thread, int count); | |
| 321 | 358 |
| 322 // Accessor, that provides default value when there is no death thread. | 359 SerializedBirthOnThread birth; |
| 323 const std::string DeathThreadName() const; | 360 SerializedDeathData death_data; |
| 324 | 361 std::string death_thread_name; |
| 325 // Construct a DictionaryValue instance containing all our data recursively. | |
| 326 // The caller assumes ownership of the memory in the returned instance. | |
| 327 base::DictionaryValue* ToValue() const; | |
| 328 | |
| 329 private: | |
| 330 const BirthOnThread* birth_; // Includes Location and birth_thread. | |
| 331 const ThreadData* death_thread_; | |
| 332 DeathData death_data_; | |
| 333 }; | 362 }; |
| 334 | 363 |
| 335 //------------------------------------------------------------------------------ | 364 //------------------------------------------------------------------------------ |
| 336 // For each thread, we have a ThreadData that stores all tracking info generated | 365 // For each thread, we have a ThreadData that stores all tracking info generated |
| 337 // on this thread. This prevents the need for locking as data accumulates. | 366 // on this thread. This prevents the need for locking as data accumulates. |
| 338 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. | 367 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. |
| 339 // We also have a linked list of ThreadData instances, and that list is used to | 368 // We also have a linked list of ThreadData instances, and that list is used to |
| 340 // harvest data from all existing instances. | 369 // harvest data from all existing instances. |
| 341 | 370 |
| 371 struct SerializedProcessData; |
| 342 class BASE_EXPORT ThreadData { | 372 class BASE_EXPORT ThreadData { |
| 343 public: | 373 public: |
| 344 // Current allowable states of the tracking system. The states can vary | 374 // Current allowable states of the tracking system. The states can vary |
| 345 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. | 375 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. |
| 346 enum Status { | 376 enum Status { |
| 347 UNINITIALIZED, // PRistine, link-time state before running. | 377 UNINITIALIZED, // PRistine, link-time state before running. |
| 348 DORMANT_DURING_TESTS, // Only used during testing. | 378 DORMANT_DURING_TESTS, // Only used during testing. |
| 349 DEACTIVATED, // No longer recording profling. | 379 DEACTIVATED, // No longer recording profling. |
| 350 PROFILING_ACTIVE, // Recording profiles (no parent-child links). | 380 PROFILING_ACTIVE, // Recording profiles (no parent-child links). |
| 351 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. | 381 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 362 // set *before* any births on the threads have taken place. It is generally | 392 // set *before* any births on the threads have taken place. It is generally |
| 363 // only used by the message loop, which has a well defined thread name. | 393 // only used by the message loop, which has a well defined thread name. |
| 364 static void InitializeThreadContext(const std::string& suggested_name); | 394 static void InitializeThreadContext(const std::string& suggested_name); |
| 365 | 395 |
| 366 // Using Thread Local Store, find the current instance for collecting data. | 396 // Using Thread Local Store, find the current instance for collecting data. |
| 367 // If an instance does not exist, construct one (and remember it for use on | 397 // If an instance does not exist, construct one (and remember it for use on |
| 368 // this thread. | 398 // this thread. |
| 369 // This may return NULL if the system is disabled for any reason. | 399 // This may return NULL if the system is disabled for any reason. |
| 370 static ThreadData* Get(); | 400 static ThreadData* Get(); |
| 371 | 401 |
| 372 // Constructs a DictionaryValue instance containing all recursive results in | 402 // Fills |process_data| with all the recursive results in our process. |
| 373 // our process. The caller assumes ownership of the memory in the returned | 403 // During the scavenging, if |reset_max| is true, then the DeathData instances |
| 374 // instance. During the scavenging, if |reset_max| is true, then the | 404 // max-values are reset to zero during this scan. |
| 375 // DeathData instances max-values are reset to zero during this scan. | 405 static void ToSerializedProcessData(bool reset_max, |
| 376 static base::DictionaryValue* ToValue(bool reset_max); | 406 SerializedProcessData* process_data); |
| 377 | 407 |
| 378 // Finds (or creates) a place to count births from the given location in this | 408 // Finds (or creates) a place to count births from the given location in this |
| 379 // thread, and increment that tally. | 409 // thread, and increment that tally. |
| 380 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. | 410 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. |
| 381 static Births* TallyABirthIfActive(const Location& location); | 411 static Births* TallyABirthIfActive(const Location& location); |
| 382 | 412 |
| 383 // Records the end of a timed run of an object. The |completed_task| contains | 413 // Records the end of a timed run of an object. The |completed_task| contains |
| 384 // a pointer to a Births, the time_posted, and a delayed_start_time if any. | 414 // a pointer to a Births, the time_posted, and a delayed_start_time if any. |
| 385 // The |start_of_run| indicates when we started to perform the run of the | 415 // The |start_of_run| indicates when we started to perform the run of the |
| 386 // task. The delayed_start_time is non-null for tasks that were posted as | 416 // task. The delayed_start_time is non-null for tasks that were posted as |
| (...skipping 21 matching lines...) Expand all Loading... |
| 408 | 438 |
| 409 // Record the end of execution in region, generally corresponding to a scope | 439 // Record the end of execution in region, generally corresponding to a scope |
| 410 // being exited. | 440 // being exited. |
| 411 static void TallyRunInAScopedRegionIfTracking( | 441 static void TallyRunInAScopedRegionIfTracking( |
| 412 const Births* birth, | 442 const Births* birth, |
| 413 const TrackedTime& start_of_run, | 443 const TrackedTime& start_of_run, |
| 414 const TrackedTime& end_of_run); | 444 const TrackedTime& end_of_run); |
| 415 | 445 |
| 416 const std::string thread_name() const; | 446 const std::string thread_name() const; |
| 417 | 447 |
| 418 // Snapshot (under a lock) copies of the maps in each ThreadData instance. For | |
| 419 // each set of maps (BirthMap, DeathMap, and ParentChildSet) call the Append() | |
| 420 // method of the |target| DataCollector. If |reset_max| is true, then the max | |
| 421 // values in each DeathData instance should be reset during the scan. | |
| 422 static void SendAllMaps(bool reset_max, class DataCollector* target); | |
| 423 | |
| 424 // Hack: asynchronously clear all birth counts and death tallies data values | 448 // Hack: asynchronously clear all birth counts and death tallies data values |
| 425 // in all ThreadData instances. The numerical (zeroing) part is done without | 449 // in all ThreadData instances. The numerical (zeroing) part is done without |
| 426 // use of a locks or atomics exchanges, and may (for int64 values) produce | 450 // use of a locks or atomics exchanges, and may (for int64 values) produce |
| 427 // bogus counts VERY rarely. | 451 // bogus counts VERY rarely. |
| 428 static void ResetAllThreadData(); | 452 static void ResetAllThreadData(); |
| 429 | 453 |
| 430 // Initializes all statics if needed (this initialization call should be made | 454 // Initializes all statics if needed (this initialization call should be made |
| 431 // while we are single threaded). Returns false if unable to initialize. | 455 // while we are single threaded). Returns false if unable to initialize. |
| 432 static bool Initialize(); | 456 static bool Initialize(); |
| 433 | 457 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 | 535 |
| 512 | 536 |
| 513 // In this thread's data, record a new birth. | 537 // In this thread's data, record a new birth. |
| 514 Births* TallyABirth(const Location& location); | 538 Births* TallyABirth(const Location& location); |
| 515 | 539 |
| 516 // Find a place to record a death on this thread. | 540 // Find a place to record a death on this thread. |
| 517 void TallyADeath(const Births& birth, | 541 void TallyADeath(const Births& birth, |
| 518 DurationInt queue_duration, | 542 DurationInt queue_duration, |
| 519 DurationInt duration); | 543 DurationInt duration); |
| 520 | 544 |
| 545 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData |
| 546 // instance. Also updates the |birth_counts| tally for each task to keep |
| 547 // track of the number of living instances of the task. If |reset_max| is |
| 548 // true, then the max values in each DeathData instance should be reset during |
| 549 // the scan. |
| 550 static void SerializeAllExecutedTasks( |
| 551 bool reset_max, |
| 552 SerializedProcessData* process_data, |
| 553 std::map<const BirthOnThread*, int>* birth_counts); |
| 554 |
| 555 // Snapshots (under a lock) the profiled data for the tasks for this thread |
| 556 // and serializes all of the executed tasks' data -- i.e. the data for the |
| 557 // tasks with with entries in the death_map_ -- into |process_data|. Also |
| 558 // updates the |birth_counts| tally for each task to keep track of the number |
| 559 // of living instances of the task. If |reset_max| is true, then the max |
| 560 // values in each DeathData instance should be reset during the scan. |
| 561 void SerializeExecutedTasks( |
| 562 bool reset_max, |
| 563 SerializedProcessData* process_data, |
| 564 std::map<const BirthOnThread*, int>* birth_counts); |
| 565 |
| 521 // Using our lock, make a copy of the specified maps. This call may be made | 566 // Using our lock, make a copy of the specified maps. This call may be made |
| 522 // on non-local threads, which necessitate the use of the lock to prevent | 567 // on non-local threads, which necessitate the use of the lock to prevent |
| 523 // the map(s) from being reallocaed while they are copied. If |reset_max| is | 568 // the map(s) from being reallocaed while they are copied. If |reset_max| is |
| 524 // true, then, just after we copy the DeathMap, we will set the max values to | 569 // true, then, just after we copy the DeathMap, we will set the max values to |
| 525 // zero in the active DeathMap (not the snapshot). | 570 // zero in the active DeathMap (not the snapshot). |
| 526 void SnapshotMaps(bool reset_max, | 571 void SnapshotMaps(bool reset_max, |
| 527 BirthMap* birth_map, | 572 BirthMap* birth_map, |
| 528 DeathMap* death_map, | 573 DeathMap* death_map, |
| 529 ParentChildSet* parent_child_set); | 574 ParentChildSet* parent_child_set); |
| 530 | 575 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 // Record of what the incarnation_counter_ was when this instance was created. | 700 // Record of what the incarnation_counter_ was when this instance was created. |
| 656 // If the incarnation_counter_ has changed, then we avoid pushing into the | 701 // If the incarnation_counter_ has changed, then we avoid pushing into the |
| 657 // pool (this is only critical in tests which go through multiple | 702 // pool (this is only critical in tests which go through multiple |
| 658 // incarnations). | 703 // incarnations). |
| 659 int incarnation_count_for_pool_; | 704 int incarnation_count_for_pool_; |
| 660 | 705 |
| 661 DISALLOW_COPY_AND_ASSIGN(ThreadData); | 706 DISALLOW_COPY_AND_ASSIGN(ThreadData); |
| 662 }; | 707 }; |
| 663 | 708 |
| 664 //------------------------------------------------------------------------------ | 709 //------------------------------------------------------------------------------ |
| 665 // DataCollector is a container class for Snapshot and BirthOnThread count | 710 // A serialized representation of a (parent, child) task pair, for tracking |
| 666 // items. | 711 // hierarchical profiles. |
| 667 | 712 |
| 668 class BASE_EXPORT DataCollector { | 713 struct BASE_EXPORT SerializedParentChildPair { |
| 669 public: | 714 public: |
| 670 typedef std::vector<Snapshot> Collection; | 715 SerializedParentChildPair(); |
| 716 SerializedParentChildPair(const ThreadData::ParentChildPair& parent_child); |
| 717 ~SerializedParentChildPair(); |
| 671 | 718 |
| 672 // Construct with a list of how many threads should contribute. This helps us | |
| 673 // determine (in the async case) when we are done with all contributions. | |
| 674 DataCollector(); | |
| 675 ~DataCollector(); | |
| 676 | |
| 677 // Adds all stats from the indicated thread into our arrays. Accepts copies | |
| 678 // of the birth_map and death_map, so that the data will not change during the | |
| 679 // iterations and processing. | |
| 680 void Append(const ThreadData &thread_data, | |
| 681 const ThreadData::BirthMap& birth_map, | |
| 682 const ThreadData::DeathMap& death_map, | |
| 683 const ThreadData::ParentChildSet& parent_child_set); | |
| 684 | |
| 685 // After the accumulation phase, the following accessor is used to process the | |
| 686 // data (i.e., sort it, filter it, etc.). | |
| 687 Collection* collection(); | |
| 688 | |
| 689 // Adds entries for all the remaining living objects (objects that have | |
| 690 // tallied a birth, but have not yet tallied a matching death, and hence must | |
| 691 // be either running, queued up, or being held in limbo for future posting). | |
| 692 // This should be called after all known ThreadData instances have been | |
| 693 // processed using Append(). | |
| 694 void AddListOfLivingObjects(); | |
| 695 | |
| 696 // Generates a ListValue representation of the vector of snapshots, and | |
| 697 // inserts the results into |dictionary|. | |
| 698 void ToValue(base::DictionaryValue* dictionary) const; | 719 void ToValue(base::DictionaryValue* dictionary) const; |
| 699 | 720 |
| 700 private: | 721 SerializedBirthOnThread parent; |
| 701 typedef std::map<const BirthOnThread*, int> BirthCount; | 722 SerializedBirthOnThread child; |
| 723 }; |
| 702 | 724 |
| 703 // The array that we collect data into. | 725 //------------------------------------------------------------------------------ |
| 704 Collection collection_; | 726 // A serialized representation of the list of ThreadData objects for a process. |
| 705 | 727 |
| 706 // The total number of births recorded at each location for which we have not | 728 struct BASE_EXPORT SerializedProcessData { |
| 707 // seen a death count. This map changes as we do Append() calls, and is later | 729 public: |
| 708 // used by AddListOfLivingObjects() to gather up unaccounted for births. | 730 SerializedProcessData(); |
| 709 BirthCount global_birth_count_; | 731 ~SerializedProcessData(); |
| 710 | 732 |
| 711 // The complete list of parent-child relationships among tasks. | 733 void ToValue(base::DictionaryValue* dictionary) const; |
| 712 ThreadData::ParentChildSet parent_child_set_; | |
| 713 | 734 |
| 714 DISALLOW_COPY_AND_ASSIGN(DataCollector); | 735 std::vector<SerializedSnapshot> snapshots; |
| 736 std::vector<SerializedParentChildPair> descendants; |
| 737 int process_id; |
| 715 }; | 738 }; |
| 716 | 739 |
| 717 } // namespace tracked_objects | 740 } // namespace tracked_objects |
| 718 | 741 |
| 719 #endif // BASE_TRACKED_OBJECTS_H_ | 742 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |