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

Side by Side Diff: base/tracked_objects.h

Issue 9702014: [UMA] Use proper C++ objects to serialize tracked_objects across process boundaries. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix base_unittests failures Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_TRACKED_OBJECTS_H_ 5 #ifndef BASE_TRACKED_OBJECTS_H_
6 #define BASE_TRACKED_OBJECTS_H_ 6 #define BASE_TRACKED_OBJECTS_H_
7 #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
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
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
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
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
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698