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

Side by Side Diff: base/tracked_objects.h

Issue 10077001: [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 yet another IWYU in the chromeos/ code... Created 8 years, 8 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
« no previous file with comments | « base/location.cc ('k') | base/tracked_objects.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_TRACKED_OBJECTS_H_ 5 #ifndef BASE_TRACKED_OBJECTS_H_
6 #define BASE_TRACKED_OBJECTS_H_ 6 #define BASE_TRACKED_OBJECTS_H_
7 #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 #include "base/values.h"
27 26
28 // TrackedObjects provides a database of stats about objects (generally Tasks) 27 // TrackedObjects provides a database of stats about objects (generally Tasks)
29 // that are tracked. Tracking means their birth, death, duration, birth thread, 28 // that are tracked. Tracking means their birth, death, duration, birth thread,
30 // death thread, and birth place are recorded. This data is carefully spread 29 // 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 30 // 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 31 // 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 32 // 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. 33 // the about:profiler URL, with a variety of sorting and filtering choices.
35 // 34 //
36 // These classes serve as the basis of a profiler of sorts for the Tasks system. 35 // These classes serve as the basis of a profiler of sorts for the Tasks system.
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 // very little global performance impact. 121 // very little global performance impact.
123 // 122 //
124 // The above description tries to define the high performance (run time) 123 // The above description tries to define the high performance (run time)
125 // portions of these classes. After gathering statistics, calls instigated 124 // portions of these classes. After gathering statistics, calls instigated
126 // by visiting about:profiler will assemble and aggregate data for display. The 125 // by visiting about:profiler will assemble and aggregate data for display. The
127 // following data structures are used for producing such displays. They are 126 // following data structures are used for producing such displays. They are
128 // not performance critical, and their only major constraint is that they should 127 // 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 128 // be able to run concurrently with ongoing augmentation of the birth and death
130 // data. 129 // data.
131 // 130 //
131 // This header also exports collection of classes that provide "snapshotted"
132 // representations of the core tracked_objects:: classes. These snapshotted
133 // representations are designed for safe transmission of the tracked_objects::
134 // data across process boundaries. Each consists of:
135 // (1) a default constructor, to support the IPC serialization macros,
136 // (2) a constructor that extracts data from the type being snapshotted, and
137 // (3) the snapshotted data.
138 //
132 // For a given birth location, information about births is spread across data 139 // For a given birth location, information about births is spread across data
133 // structures that are asynchronously changing on various threads. For display 140 // structures that are asynchronously changing on various threads. For
134 // purposes, we need to construct Snapshot instances for each combination of 141 // serialization and display purposes, we need to construct TaskSnapshot
135 // birth thread, death thread, and location, along with the count of such 142 // instances for each combination of birth thread, death thread, and location,
136 // lifetimes. We gather such data into a Snapshot instances, so that such 143 // 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 144 // TaskSnapshot instances, so that such instances can be sorted and
138 // processing). Snapshot instances use pointers to constant portions of the 145 // 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 // 146 //
142 // A DataCollector is a container object that holds a set of Snapshots. The 147 // The ProcessDataSnapshot struct is a serialized representation of the list
143 // statistics in a snapshot are gathered asynhcronously relative to their 148 // of ThreadData objects for a process. It holds a set of TaskSnapshots
144 // ongoing updates. It is possible, though highly unlikely, that stats could be 149 // 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 150 // 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, 151 // It is possible, though highly unlikely, that stats could be incorrectly
147 // for example, match with the number of durations we accumulated). The 152 // 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 153 // 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 154 // example, match with the number of durations we accumulated). The advantage
150 // could be corrupt, not the underlying and ongoing statistic). In constrast, 155 // 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, 156 // 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 157 // not the underlying and ongoing statistic). In constrast, pointer data that
153 // of a bad memory reference). 158 // is accessed during snapshotting is completely invariant, and hence is
154 // 159 // 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, 160 // 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 // 161 //
160 // TODO(jar): We can implement a Snapshot system that *tries* to grab the 162 // TODO(jar): We can implement a Snapshot system that *tries* to grab the
161 // snapshots on the source threads *when* they have MessageLoops available 163 // snapshots on the source threads *when* they have MessageLoops available
162 // (worker threads don't have message loops generally, and hence gathering from 164 // (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 165 // 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. 166 // 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 167 // 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 168 // 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 169 // upload via UMA (where correctness of data may be more significant than for a
168 // single screen of about:profiler). 170 // single screen of about:profiler).
(...skipping 20 matching lines...) Expand all
189 namespace tracked_objects { 191 namespace tracked_objects {
190 192
191 //------------------------------------------------------------------------------ 193 //------------------------------------------------------------------------------
192 // For a specific thread, and a specific birth place, the collection of all 194 // 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). 195 // death info (with tallies for each death thread, to prevent access conflicts).
194 class ThreadData; 196 class ThreadData;
195 class BASE_EXPORT BirthOnThread { 197 class BASE_EXPORT BirthOnThread {
196 public: 198 public:
197 BirthOnThread(const Location& location, const ThreadData& current); 199 BirthOnThread(const Location& location, const ThreadData& current);
198 200
199 const Location location() const; 201 const Location location() const { return location_; }
200 const ThreadData* birth_thread() const; 202 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 203
208 private: 204 private:
209 // File/lineno of birth. This defines the essence of the task, as the context 205 // 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 206 // of the birth (construction) often tell what the item is for. This field
211 // is const, and hence safe to access from any thread. 207 // is const, and hence safe to access from any thread.
212 const Location location_; 208 const Location location_;
213 209
214 // The thread that records births into this object. Only this thread is 210 // The thread that records births into this object. Only this thread is
215 // allowed to update birth_count_ (which changes over time). 211 // allowed to update birth_count_ (which changes over time).
216 const ThreadData* const birth_thread_; 212 const ThreadData* const birth_thread_;
217 213
218 DISALLOW_COPY_AND_ASSIGN(BirthOnThread); 214 DISALLOW_COPY_AND_ASSIGN(BirthOnThread);
219 }; 215 };
220 216
221 //------------------------------------------------------------------------------ 217 //------------------------------------------------------------------------------
218 // A "snapshotted" representation of the BirthOnThread class.
219
220 struct BASE_EXPORT BirthOnThreadSnapshot {
221 BirthOnThreadSnapshot();
222 explicit BirthOnThreadSnapshot(const BirthOnThread& birth);
223 ~BirthOnThreadSnapshot();
224
225 LocationSnapshot location;
226 std::string thread_name;
227 };
228
229 //------------------------------------------------------------------------------
222 // A class for accumulating counts of births (without bothering with a map<>). 230 // A class for accumulating counts of births (without bothering with a map<>).
223 231
224 class BASE_EXPORT Births: public BirthOnThread { 232 class BASE_EXPORT Births: public BirthOnThread {
225 public: 233 public:
226 Births(const Location& location, const ThreadData& current); 234 Births(const Location& location, const ThreadData& current);
227 235
228 int birth_count() const; 236 int birth_count() const;
229 237
230 // When we have a birth we update the count for this BirhPLace. 238 // When we have a birth we update the count for this birthplace.
231 void RecordBirth(); 239 void RecordBirth();
232 240
233 // When a birthplace is changed (updated), we need to decrement the counter 241 // When a birthplace is changed (updated), we need to decrement the counter
234 // for the old instance. 242 // for the old instance.
235 void ForgetBirth(); 243 void ForgetBirth();
236 244
237 // Hack to quickly reset all counts to zero. 245 // Hack to quickly reset all counts to zero.
238 void Clear(); 246 void Clear();
239 247
240 private: 248 private:
(...skipping 17 matching lines...) Expand all
258 // threads, we create DeathData stats that tally the number of births without 266 // threads, we create DeathData stats that tally the number of births without
259 // a corresponding death. 267 // a corresponding death.
260 explicit DeathData(int count); 268 explicit DeathData(int count);
261 269
262 // Update stats for a task destruction (death) that had a Run() time of 270 // Update stats for a task destruction (death) that had a Run() time of
263 // |duration|, and has had a queueing delay of |queue_duration|. 271 // |duration|, and has had a queueing delay of |queue_duration|.
264 void RecordDeath(const int32 queue_duration, 272 void RecordDeath(const int32 queue_duration,
265 const int32 run_duration, 273 const int32 run_duration,
266 int random_number); 274 int random_number);
267 275
268 // Metrics accessors, used only in tests. 276 // Metrics accessors, used only for serialization and in tests.
269 int count() const; 277 int count() const;
270 int32 run_duration_sum() const; 278 int32 run_duration_sum() const;
271 int32 run_duration_max() const; 279 int32 run_duration_max() const;
272 int32 run_duration_sample() const; 280 int32 run_duration_sample() const;
273 int32 queue_duration_sum() const; 281 int32 queue_duration_sum() const;
274 int32 queue_duration_max() const; 282 int32 queue_duration_max() const;
275 int32 queue_duration_sample() const; 283 int32 queue_duration_sample() const;
276 284
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. 285 // Reset the max values to zero.
282 void ResetMax(); 286 void ResetMax();
283 287
284 // Reset all tallies to zero. This is used as a hack on realtime data. 288 // Reset all tallies to zero. This is used as a hack on realtime data.
285 void Clear(); 289 void Clear();
286 290
287 private: 291 private:
288 // Members are ordered from most regularly read and updated, to least 292 // Members are ordered from most regularly read and updated, to least
289 // frequently used. This might help a bit with cache lines. 293 // frequently used. This might help a bit with cache lines.
290 // Number of runs seen (divisor for calculating averages). 294 // Number of runs seen (divisor for calculating averages).
291 int count_; 295 int count_;
292 // Basic tallies, used to compute averages. 296 // Basic tallies, used to compute averages.
293 int32 run_duration_sum_; 297 int32 run_duration_sum_;
294 int32 queue_duration_sum_; 298 int32 queue_duration_sum_;
295 // Max values, used by local visualization routines. These are often read, 299 // Max values, used by local visualization routines. These are often read,
296 // but rarely updated. 300 // but rarely updated.
297 int32 run_duration_max_; 301 int32 run_duration_max_;
298 int32 queue_duration_max_; 302 int32 queue_duration_max_;
299 // Samples, used by by crowd sourcing gatherers. These are almost never read, 303 // Samples, used by crowd sourcing gatherers. These are almost never read,
300 // and rarely updated. 304 // and rarely updated.
301 int32 run_duration_sample_; 305 int32 run_duration_sample_;
302 int32 queue_duration_sample_; 306 int32 queue_duration_sample_;
303 }; 307 };
304 308
305 //------------------------------------------------------------------------------ 309 //------------------------------------------------------------------------------
310 // A "snapshotted" representation of the DeathData class.
311
312 struct BASE_EXPORT DeathDataSnapshot {
313 DeathDataSnapshot();
314 explicit DeathDataSnapshot(const DeathData& death_data);
315 ~DeathDataSnapshot();
316
317 int count;
318 int32 run_duration_sum;
319 int32 run_duration_max;
320 int32 run_duration_sample;
321 int32 queue_duration_sum;
322 int32 queue_duration_max;
323 int32 queue_duration_sample;
324 };
325
326 //------------------------------------------------------------------------------
306 // A temporary collection of data that can be sorted and summarized. It is 327 // 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 328 // gathered (carefully) from many threads. Instances are held in arrays and
308 // processed, filtered, and rendered. 329 // processed, filtered, and rendered.
309 // The source of this data was collected on many threads, and is asynchronously 330 // The source of this data was collected on many threads, and is asynchronously
310 // changing. The data in this instance is not asynchronously changing. 331 // changing. The data in this instance is not asynchronously changing.
311 332
312 class BASE_EXPORT Snapshot { 333 struct BASE_EXPORT TaskSnapshot {
313 public: 334 TaskSnapshot();
314 // When snapshotting a full life cycle set (birth-to-death), use this: 335 TaskSnapshot(const BirthOnThread& birth,
315 Snapshot(const BirthOnThread& birth_on_thread, 336 const DeathData& death_data,
316 const ThreadData& death_thread, 337 const std::string& death_thread_name);
317 const DeathData& death_data); 338 ~TaskSnapshot();
318 339
319 // When snapshotting a birth, with no death yet, use this: 340 BirthOnThreadSnapshot birth;
320 Snapshot(const BirthOnThread& birth_on_thread, int count); 341 DeathDataSnapshot death_data;
321 342 std::string death_thread_name;
322 // Accessor, that provides default value when there is no death thread.
323 const std::string DeathThreadName() const;
324
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 }; 343 };
334 344
335 //------------------------------------------------------------------------------ 345 //------------------------------------------------------------------------------
336 // For each thread, we have a ThreadData that stores all tracking info generated 346 // 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. 347 // on this thread. This prevents the need for locking as data accumulates.
338 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. 348 // 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 349 // We also have a linked list of ThreadData instances, and that list is used to
340 // harvest data from all existing instances. 350 // harvest data from all existing instances.
341 351
352 struct ProcessDataSnapshot;
342 class BASE_EXPORT ThreadData { 353 class BASE_EXPORT ThreadData {
343 public: 354 public:
344 // Current allowable states of the tracking system. The states can vary 355 // Current allowable states of the tracking system. The states can vary
345 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. 356 // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED.
346 enum Status { 357 enum Status {
347 UNINITIALIZED, // PRistine, link-time state before running. 358 UNINITIALIZED, // PRistine, link-time state before running.
348 DORMANT_DURING_TESTS, // Only used during testing. 359 DORMANT_DURING_TESTS, // Only used during testing.
349 DEACTIVATED, // No longer recording profling. 360 DEACTIVATED, // No longer recording profling.
350 PROFILING_ACTIVE, // Recording profiles (no parent-child links). 361 PROFILING_ACTIVE, // Recording profiles (no parent-child links).
351 PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. 362 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 373 // 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. 374 // only used by the message loop, which has a well defined thread name.
364 static void InitializeThreadContext(const std::string& suggested_name); 375 static void InitializeThreadContext(const std::string& suggested_name);
365 376
366 // Using Thread Local Store, find the current instance for collecting data. 377 // 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 378 // If an instance does not exist, construct one (and remember it for use on
368 // this thread. 379 // this thread.
369 // This may return NULL if the system is disabled for any reason. 380 // This may return NULL if the system is disabled for any reason.
370 static ThreadData* Get(); 381 static ThreadData* Get();
371 382
372 // Constructs a DictionaryValue instance containing all recursive results in 383 // Fills |process_data| with all the recursive results in our process.
373 // our process. The caller assumes ownership of the memory in the returned 384 // During the scavenging, if |reset_max| is true, then the DeathData instances
374 // instance. During the scavenging, if |reset_max| is true, then the 385 // max-values are reset to zero during this scan.
375 // DeathData instances max-values are reset to zero during this scan. 386 static void Snapshot(bool reset_max, ProcessDataSnapshot* process_data);
376 static base::DictionaryValue* ToValue(bool reset_max);
377 387
378 // Finds (or creates) a place to count births from the given location in this 388 // Finds (or creates) a place to count births from the given location in this
379 // thread, and increment that tally. 389 // thread, and increment that tally.
380 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. 390 // TallyABirthIfActive will returns NULL if the birth cannot be tallied.
381 static Births* TallyABirthIfActive(const Location& location); 391 static Births* TallyABirthIfActive(const Location& location);
382 392
383 // Records the end of a timed run of an object. The |completed_task| contains 393 // 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. 394 // 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 395 // 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 396 // task. The delayed_start_time is non-null for tasks that were posted as
(...skipping 21 matching lines...) Expand all
408 418
409 // Record the end of execution in region, generally corresponding to a scope 419 // Record the end of execution in region, generally corresponding to a scope
410 // being exited. 420 // being exited.
411 static void TallyRunInAScopedRegionIfTracking( 421 static void TallyRunInAScopedRegionIfTracking(
412 const Births* birth, 422 const Births* birth,
413 const TrackedTime& start_of_run, 423 const TrackedTime& start_of_run,
414 const TrackedTime& end_of_run); 424 const TrackedTime& end_of_run);
415 425
416 const std::string thread_name() const; 426 const std::string thread_name() const;
417 427
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 428 // Hack: asynchronously clear all birth counts and death tallies data values
425 // in all ThreadData instances. The numerical (zeroing) part is done without 429 // 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 430 // use of a locks or atomics exchanges, and may (for int64 values) produce
427 // bogus counts VERY rarely. 431 // bogus counts VERY rarely.
428 static void ResetAllThreadData(); 432 static void ResetAllThreadData();
429 433
430 // Initializes all statics if needed (this initialization call should be made 434 // Initializes all statics if needed (this initialization call should be made
431 // while we are single threaded). Returns false if unable to initialize. 435 // while we are single threaded). Returns false if unable to initialize.
432 static bool Initialize(); 436 static bool Initialize();
433 437
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it 487 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it
484 // in production code. 488 // in production code.
485 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a 489 // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a
486 // better change of optimizing (inlining? etc.) private methods (knowing that 490 // better change of optimizing (inlining? etc.) private methods (knowing that
487 // there will be no need for an external entry point). 491 // there will be no need for an external entry point).
488 friend class TrackedObjectsTest; 492 friend class TrackedObjectsTest;
489 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); 493 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown);
490 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); 494 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown);
491 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); 495 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest);
492 496
497 typedef std::map<const BirthOnThread*, int> BirthCountMap;
498
493 // Worker thread construction creates a name since there is none. 499 // Worker thread construction creates a name since there is none.
494 explicit ThreadData(int thread_number); 500 explicit ThreadData(int thread_number);
495 501
496 // Message loop based construction should provide a name. 502 // Message loop based construction should provide a name.
497 explicit ThreadData(const std::string& suggested_name); 503 explicit ThreadData(const std::string& suggested_name);
498 504
499 ~ThreadData(); 505 ~ThreadData();
500 506
501 // Push this instance to the head of all_thread_data_list_head_, linking it to 507 // Push this instance to the head of all_thread_data_list_head_, linking it to
502 // the previous head. This is performed after each construction, and leaves 508 // the previous head. This is performed after each construction, and leaves
503 // the instance permanently on that list. 509 // the instance permanently on that list.
504 void PushToHeadOfList(); 510 void PushToHeadOfList();
505 511
506 // (Thread safe) Get start of list of all ThreadData instances using the lock. 512 // (Thread safe) Get start of list of all ThreadData instances using the lock.
507 static ThreadData* first(); 513 static ThreadData* first();
508 514
509 // Iterate through the null terminated list of ThreadData instances. 515 // Iterate through the null terminated list of ThreadData instances.
510 ThreadData* next() const; 516 ThreadData* next() const;
511 517
512 518
513 // In this thread's data, record a new birth. 519 // In this thread's data, record a new birth.
514 Births* TallyABirth(const Location& location); 520 Births* TallyABirth(const Location& location);
515 521
516 // Find a place to record a death on this thread. 522 // Find a place to record a death on this thread.
517 void TallyADeath(const Births& birth, int32 queue_duration, int32 duration); 523 void TallyADeath(const Births& birth, int32 queue_duration, int32 duration);
518 524
525 // Snapshot (under a lock) the profiled data for the tasks in each ThreadData
526 // instance. Also updates the |birth_counts| tally for each task to keep
527 // track of the number of living instances of the task. If |reset_max| is
528 // true, then the max values in each DeathData instance are reset during the
529 // scan.
530 static void SnapshotAllExecutedTasks(bool reset_max,
531 ProcessDataSnapshot* process_data,
532 BirthCountMap* birth_counts);
533
534 // Snapshots (under a lock) the profiled data for the tasks for this thread
535 // and writes all of the executed tasks' data -- i.e. the data for the tasks
536 // with with entries in the death_map_ -- into |process_data|. Also updates
537 // the |birth_counts| tally for each task to keep track of the number of
538 // living instances of the task -- that is, each task maps to the number of
539 // births for the task that have not yet been balanced by a death. If
540 // |reset_max| is true, then the max values in each DeathData instance are
541 // reset during the scan.
542 void SnapshotExecutedTasks(bool reset_max,
543 ProcessDataSnapshot* process_data,
544 BirthCountMap* birth_counts);
545
519 // Using our lock, make a copy of the specified maps. This call may be made 546 // Using our lock, make a copy of the specified maps. This call may be made
520 // on non-local threads, which necessitate the use of the lock to prevent 547 // on non-local threads, which necessitate the use of the lock to prevent
521 // the map(s) from being reallocaed while they are copied. If |reset_max| is 548 // the map(s) from being reallocaed while they are copied. If |reset_max| is
522 // true, then, just after we copy the DeathMap, we will set the max values to 549 // true, then, just after we copy the DeathMap, we will set the max values to
523 // zero in the active DeathMap (not the snapshot). 550 // zero in the active DeathMap (not the snapshot).
524 void SnapshotMaps(bool reset_max, 551 void SnapshotMaps(bool reset_max,
525 BirthMap* birth_map, 552 BirthMap* birth_map,
526 DeathMap* death_map, 553 DeathMap* death_map,
527 ParentChildSet* parent_child_set); 554 ParentChildSet* parent_child_set);
528 555
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 // Record of what the incarnation_counter_ was when this instance was created. 680 // Record of what the incarnation_counter_ was when this instance was created.
654 // If the incarnation_counter_ has changed, then we avoid pushing into the 681 // If the incarnation_counter_ has changed, then we avoid pushing into the
655 // pool (this is only critical in tests which go through multiple 682 // pool (this is only critical in tests which go through multiple
656 // incarnations). 683 // incarnations).
657 int incarnation_count_for_pool_; 684 int incarnation_count_for_pool_;
658 685
659 DISALLOW_COPY_AND_ASSIGN(ThreadData); 686 DISALLOW_COPY_AND_ASSIGN(ThreadData);
660 }; 687 };
661 688
662 //------------------------------------------------------------------------------ 689 //------------------------------------------------------------------------------
663 // DataCollector is a container class for Snapshot and BirthOnThread count 690 // A snapshotted representation of a (parent, child) task pair, for tracking
664 // items. 691 // hierarchical profiles.
665 692
666 class BASE_EXPORT DataCollector { 693 struct BASE_EXPORT ParentChildPairSnapshot {
667 public: 694 public:
668 typedef std::vector<Snapshot> Collection; 695 ParentChildPairSnapshot();
696 explicit ParentChildPairSnapshot(
697 const ThreadData::ParentChildPair& parent_child);
698 ~ParentChildPairSnapshot();
669 699
670 // Construct with a list of how many threads should contribute. This helps us 700 BirthOnThreadSnapshot parent;
671 // determine (in the async case) when we are done with all contributions. 701 BirthOnThreadSnapshot child;
672 DataCollector(); 702 };
673 ~DataCollector();
674 703
675 // Adds all stats from the indicated thread into our arrays. Accepts copies 704 //------------------------------------------------------------------------------
676 // of the birth_map and death_map, so that the data will not change during the 705 // A snapshotted representation of the list of ThreadData objects for a process.
677 // iterations and processing.
678 void Append(const ThreadData &thread_data,
679 const ThreadData::BirthMap& birth_map,
680 const ThreadData::DeathMap& death_map,
681 const ThreadData::ParentChildSet& parent_child_set);
682 706
683 // After the accumulation phase, the following accessor is used to process the 707 struct BASE_EXPORT ProcessDataSnapshot {
684 // data (i.e., sort it, filter it, etc.). 708 public:
685 Collection* collection(); 709 ProcessDataSnapshot();
710 ~ProcessDataSnapshot();
686 711
687 // Adds entries for all the remaining living objects (objects that have 712 std::vector<TaskSnapshot> tasks;
688 // tallied a birth, but have not yet tallied a matching death, and hence must 713 std::vector<ParentChildPairSnapshot> descendants;
689 // be either running, queued up, or being held in limbo for future posting). 714 int process_id;
690 // This should be called after all known ThreadData instances have been
691 // processed using Append().
692 void AddListOfLivingObjects();
693
694 // Generates a ListValue representation of the vector of snapshots, and
695 // inserts the results into |dictionary|.
696 void ToValue(base::DictionaryValue* dictionary) const;
697
698 private:
699 typedef std::map<const BirthOnThread*, int> BirthCount;
700
701 // The array that we collect data into.
702 Collection collection_;
703
704 // The total number of births recorded at each location for which we have not
705 // seen a death count. This map changes as we do Append() calls, and is later
706 // used by AddListOfLivingObjects() to gather up unaccounted for births.
707 BirthCount global_birth_count_;
708
709 // The complete list of parent-child relationships among tasks.
710 ThreadData::ParentChildSet parent_child_set_;
711
712 DISALLOW_COPY_AND_ASSIGN(DataCollector);
713 }; 715 };
714 716
715 } // namespace tracked_objects 717 } // namespace tracked_objects
716 718
717 #endif // BASE_TRACKED_OBJECTS_H_ 719 #endif // BASE_TRACKED_OBJECTS_H_
OLDNEW
« no previous file with comments | « base/location.cc ('k') | base/tracked_objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698