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

Side by Side Diff: base/tracked_objects.h

Issue 8313013: Support JSON encoding of data for about:tracking information (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 2 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <stack>
10 #include <string> 11 #include <string>
11 #include <vector> 12 #include <vector>
12 13
13 #include "base/base_export.h" 14 #include "base/base_export.h"
14 #include "base/location.h" 15 #include "base/location.h"
15 #include "base/time.h" 16 #include "base/time.h"
16 #include "base/synchronization/lock.h" 17 #include "base/synchronization/lock.h"
17 #include "base/threading/thread_local_storage.h" 18 #include "base/threading/thread_local_storage.h"
19 #include "base/values.h"
18 20
19 // TrackedObjects provides a database of stats about objects (generally Tasks) 21 // TrackedObjects provides a database of stats about objects (generally Tasks)
20 // that are tracked. Tracking means their birth, death, duration, birth thread, 22 // that are tracked. Tracking means their birth, death, duration, birth thread,
21 // death thread, and birth place are recorded. This data is carefully spread 23 // death thread, and birth place are recorded. This data is carefully spread
22 // across a series of objects so that the counts and times can be rapidly 24 // across a series of objects so that the counts and times can be rapidly
23 // updated without (usually) having to lock the data, and hence there is usually 25 // updated without (usually) having to lock the data, and hence there is usually
24 // very little contention caused by the tracking. The data can be viewed via 26 // very little contention caused by the tracking. The data can be viewed via
25 // the about:tracking URL, with a variety of sorting and filtering choices. 27 // the about:tracking URL, with a variety of sorting and filtering choices.
26 // 28 //
27 // These classes serve as the basis of a profiler of sorts for the Tasks system. 29 // These classes serve as the basis of a profiler of sorts for the Tasks system.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 // ThreadData instance (for that specific thread only). The two critical items 97 // ThreadData instance (for that specific thread only). The two critical items
96 // are lists of DeathData and Births instances. These lists are maintained in 98 // are lists of DeathData and Births instances. These lists are maintained in
97 // STL maps, which are indexed by Location. As noted earlier, we can compare 99 // STL maps, which are indexed by Location. As noted earlier, we can compare
98 // locations very efficiently as we consider the underlying data (file, 100 // locations very efficiently as we consider the underlying data (file,
99 // function, line) to be atoms, and hence pointer comparison is used rather than 101 // function, line) to be atoms, and hence pointer comparison is used rather than
100 // (slow) string comparisons. 102 // (slow) string comparisons.
101 // 103 //
102 // To provide a mechanism for iterating over all "known threads," which means 104 // To provide a mechanism for iterating over all "known threads," which means
103 // threads that have recorded a birth or a death, we create a singly linked list 105 // threads that have recorded a birth or a death, we create a singly linked list
104 // of ThreadData instances. Each such instance maintains a pointer to the next 106 // of ThreadData instances. Each such instance maintains a pointer to the next
105 // one. A static member of ThreadData provides a pointer to the first_ item on 107 // one. A static member of ThreadData provides a pointer to the first item on
106 // this global list, and access to that first_ item requires the use of a lock_. 108 // this global list, and access via that all_thread_data_list_head_ item
109 // requires the use of the list_lock_.
107 // When new ThreadData instances is added to the global list, it is pre-pended, 110 // When new ThreadData instances is added to the global list, it is pre-pended,
108 // which ensures that any prior acquisition of the list is valid (i.e., the 111 // which ensures that any prior acquisition of the list is valid (i.e., the
109 // holder can iterate over it without fear of it changing, or the necessity of 112 // holder can iterate over it without fear of it changing, or the necessity of
110 // using an additional lock. Iterations are actually pretty rare (used 113 // using an additional lock. Iterations are actually pretty rare (used
111 // primarilly for cleanup, or snapshotting data for display), so this lock has 114 // primarilly for cleanup, or snapshotting data for display), so this lock has
112 // very little global performance impact. 115 // very little global performance impact.
113 // 116 //
114 // The above description tries to define the high performance (run time) 117 // The above description tries to define the high performance (run time)
115 // portions of these classes. After gathering statistics, calls instigated 118 // portions of these classes. After gathering statistics, calls instigated
116 // by visiting about:tracking will assemble and aggregate data for display. The 119 // by visiting about:tracking will assemble and aggregate data for display. The
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 class MessageLoop; 165 class MessageLoop;
163 166
164 namespace tracked_objects { 167 namespace tracked_objects {
165 168
166 //------------------------------------------------------------------------------ 169 //------------------------------------------------------------------------------
167 // For a specific thread, and a specific birth place, the collection of all 170 // For a specific thread, and a specific birth place, the collection of all
168 // death info (with tallies for each death thread, to prevent access conflicts). 171 // death info (with tallies for each death thread, to prevent access conflicts).
169 class ThreadData; 172 class ThreadData;
170 class BASE_EXPORT BirthOnThread { 173 class BASE_EXPORT BirthOnThread {
171 public: 174 public:
172 explicit BirthOnThread(const Location& location); 175 BirthOnThread(const Location& location, const ThreadData& current);
173 176
174 const Location location() const { return location_; } 177 const Location location() const { return location_; }
175 const ThreadData* birth_thread() const { return birth_thread_; } 178 const ThreadData* birth_thread() const { return birth_thread_; }
176 179
177 private: 180 private:
178 // File/lineno of birth. This defines the essence of the task, as the context 181 // File/lineno of birth. This defines the essence of the task, as the context
179 // of the birth (construction) often tell what the item is for. This field 182 // of the birth (construction) often tell what the item is for. This field
180 // is const, and hence safe to access from any thread. 183 // is const, and hence safe to access from any thread.
181 const Location location_; 184 const Location location_;
182 185
183 // The thread that records births into this object. Only this thread is 186 // The thread that records births into this object. Only this thread is
184 // allowed to access birth_count_ (which changes over time). 187 // allowed to update birth_count_ (which changes over time).
185 const ThreadData* birth_thread_; // The thread this birth took place on. 188 const ThreadData* const birth_thread_;
186 189
187 DISALLOW_COPY_AND_ASSIGN(BirthOnThread); 190 DISALLOW_COPY_AND_ASSIGN(BirthOnThread);
188 }; 191 };
189 192
190 //------------------------------------------------------------------------------ 193 //------------------------------------------------------------------------------
191 // A class for accumulating counts of births (without bothering with a map<>). 194 // A class for accumulating counts of births (without bothering with a map<>).
192 195
193 class BASE_EXPORT Births: public BirthOnThread { 196 class BASE_EXPORT Births: public BirthOnThread {
194 public: 197 public:
195 explicit Births(const Location& location); 198 Births(const Location& location, const ThreadData& current);
196 199
197 int birth_count() const { return birth_count_; } 200 int birth_count() const { return birth_count_; }
198 201
199 // When we have a birth we update the count for this BirhPLace. 202 // When we have a birth we update the count for this BirhPLace.
200 void RecordBirth() { ++birth_count_; } 203 void RecordBirth() { ++birth_count_; }
201 204
202 // When a birthplace is changed (updated), we need to decrement the counter 205 // When a birthplace is changed (updated), we need to decrement the counter
203 // for the old instance. 206 // for the old instance.
204 void ForgetBirth() { --birth_count_; } // We corrected a birth place. 207 void ForgetBirth() { --birth_count_; } // We corrected a birth place.
205 208
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 int count() const { return count_; } 240 int count() const { return count_; }
238 base::TimeDelta run_duration() const { return run_duration_; } 241 base::TimeDelta run_duration() const { return run_duration_; }
239 int AverageMsRunDuration() const; 242 int AverageMsRunDuration() const;
240 base::TimeDelta queue_duration() const { return queue_duration_; } 243 base::TimeDelta queue_duration() const { return queue_duration_; }
241 int AverageMsQueueDuration() const; 244 int AverageMsQueueDuration() const;
242 245
243 // Accumulate metrics from other into this. This method is never used on 246 // Accumulate metrics from other into this. This method is never used on
244 // realtime statistics, and only used in snapshots and aggregatinos. 247 // realtime statistics, and only used in snapshots and aggregatinos.
245 void AddDeathData(const DeathData& other); 248 void AddDeathData(const DeathData& other);
246 249
247 // Simple print of internal state. 250 // Simple print of internal state for use in line of HTML.
248 void Write(std::string* output) const; 251 void WriteHTML(std::string* output) const;
252
253 // Constructe a DictionaryValue instance containing all our stats. The caller
eroman 2011/10/24 22:23:04 typo: construct
jar (doing other things) 2011/10/27 06:23:35 Done.
254 // assumes ownership of the returned instance.
255 base::DictionaryValue* ToValue() const;
249 256
250 // Reset all tallies to zero. This is used as a hack on realtime data. 257 // Reset all tallies to zero. This is used as a hack on realtime data.
251 void Clear(); 258 void Clear();
252 259
253 private: 260 private:
254 int count_; // Number of destructions. 261 int count_; // Number of destructions.
255 base::TimeDelta run_duration_; // Sum of all Run()time durations. 262 base::TimeDelta run_duration_; // Sum of all Run()time durations.
256 base::TimeDelta queue_duration_; // Sum of all queue time durations. 263 base::TimeDelta queue_duration_; // Sum of all queue time durations.
257 }; 264 };
258 265
(...skipping 25 matching lines...) Expand all
284 int AverageMsRunDuration() const { 291 int AverageMsRunDuration() const {
285 return death_data_.AverageMsRunDuration(); 292 return death_data_.AverageMsRunDuration();
286 } 293 }
287 base::TimeDelta queue_duration() const { 294 base::TimeDelta queue_duration() const {
288 return death_data_.queue_duration(); 295 return death_data_.queue_duration();
289 } 296 }
290 int AverageMsQueueDuration() const { 297 int AverageMsQueueDuration() const {
291 return death_data_.AverageMsQueueDuration(); 298 return death_data_.AverageMsQueueDuration();
292 } 299 }
293 300
294 void Write(std::string* output) const; 301 // Emit contents for use in a line of HTML
302 void WriteHTML(std::string* output) const;
303
304 // Construct a DictionaryValue instance containing all our data recursively.
305 // The caller assumes ownership of the memory in the returned instance.
306 base::DictionaryValue* ToValue() const;
295 307
296 void Add(const Snapshot& other); 308 void Add(const Snapshot& other);
297 309
298 private: 310 private:
299 const BirthOnThread* birth_; // Includes Location and birth_thread. 311 const BirthOnThread* birth_; // Includes Location and birth_thread.
300 const ThreadData* death_thread_; 312 const ThreadData* death_thread_;
301 DeathData death_data_; 313 DeathData death_data_;
302 }; 314 };
303 315
304 //------------------------------------------------------------------------------ 316 //------------------------------------------------------------------------------
(...skipping 15 matching lines...) Expand all
320 void Append(const ThreadData& thread_data); 332 void Append(const ThreadData& thread_data);
321 333
322 // After the accumulation phase, the following accessor is used to process the 334 // After the accumulation phase, the following accessor is used to process the
323 // data. 335 // data.
324 Collection* collection(); 336 Collection* collection();
325 337
326 // After collection of death data is complete, we can add entries for all the 338 // After collection of death data is complete, we can add entries for all the
327 // remaining living objects. 339 // remaining living objects.
328 void AddListOfLivingObjects(); 340 void AddListOfLivingObjects();
329 341
342 // Generate a ListValue representation of the vector of snapshots. The caller
eroman 2011/10/24 22:23:04 nit: style guide says to use passive tense for fun
jar (doing other things) 2011/10/27 06:23:35 Done.
343 // assumes ownership of the memory in the returned instance.
344 base::ListValue* ToValue() const;
345
330 private: 346 private:
331 typedef std::map<const BirthOnThread*, int> BirthCount; 347 typedef std::map<const BirthOnThread*, int> BirthCount;
332 348
333 // The array that we collect data into. 349 // The array that we collect data into.
334 Collection collection_; 350 Collection collection_;
335 351
336 // The total number of births recorded at each location for which we have not 352 // The total number of births recorded at each location for which we have not
337 // seen a death count. 353 // seen a death count.
338 BirthCount global_birth_count_; 354 BirthCount global_birth_count_;
339 355
340 DISALLOW_COPY_AND_ASSIGN(DataCollector); 356 DISALLOW_COPY_AND_ASSIGN(DataCollector);
341 }; 357 };
342 358
343 //------------------------------------------------------------------------------ 359 //------------------------------------------------------------------------------
344 // Aggregation contains summaries (totals and subtotals) of groups of Snapshot 360 // Aggregation contains summaries (totals and subtotals) of groups of Snapshot
345 // instances to provide printing of these collections on a single line. 361 // instances to provide printing of these collections on a single line.
346 362
347 class BASE_EXPORT Aggregation: public DeathData { 363 class BASE_EXPORT Aggregation: public DeathData {
348 public: 364 public:
349 Aggregation(); 365 Aggregation();
350 ~Aggregation(); 366 ~Aggregation();
351 367
352 void AddDeathSnapshot(const Snapshot& snapshot); 368 void AddDeathSnapshot(const Snapshot& snapshot);
353 void AddBirths(const Births& births); 369 void AddBirths(const Births& births);
354 void AddBirth(const BirthOnThread& birth); 370 void AddBirth(const BirthOnThread& birth);
355 void AddBirthPlace(const Location& location); 371 void AddBirthPlace(const Location& location);
356 void Write(std::string* output) const; 372 void WriteHTML(std::string* output) const;
357 void Clear(); 373 void Clear();
358 374
359 private: 375 private:
360 int birth_count_; 376 int birth_count_;
361 std::map<std::string, int> birth_files_; 377 std::map<std::string, int> birth_files_;
362 std::map<Location, int> locations_; 378 std::map<Location, int> locations_;
363 std::map<const ThreadData*, int> birth_threads_; 379 std::map<const ThreadData*, int> birth_threads_;
364 DeathData death_data_; 380 DeathData death_data_;
365 std::map<const ThreadData*, int> death_threads_; 381 std::map<const ThreadData*, int> death_threads_;
366 382
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 456
441 // Parse a query to decide on sort ordering. 457 // Parse a query to decide on sort ordering.
442 bool ParseQuery(const std::string& query); 458 bool ParseQuery(const std::string& query);
443 459
444 // Output a header line that can be used to indicated what items will be 460 // Output a header line that can be used to indicated what items will be
445 // collected in the group. It lists all (potentially) tested attributes and 461 // collected in the group. It lists all (potentially) tested attributes and
446 // their values (in the sample item). 462 // their values (in the sample item).
447 bool WriteSortGrouping(const Snapshot& sample, std::string* output) const; 463 bool WriteSortGrouping(const Snapshot& sample, std::string* output) const;
448 464
449 // Output a sample, with SortGroup details not displayed. 465 // Output a sample, with SortGroup details not displayed.
450 void WriteSnapshot(const Snapshot& sample, std::string* output) const; 466 void WriteSnapshotHTML(const Snapshot& sample, std::string* output) const;
451 467
452 private: 468 private:
453 // The selector directs this instance to compare based on the specified 469 // The selector directs this instance to compare based on the specified
454 // members of the tested elements. 470 // members of the tested elements.
455 enum Selector selector_; 471 enum Selector selector_;
456 472
457 // For filtering into acceptable and unacceptable snapshot instance, the 473 // For filtering into acceptable and unacceptable snapshot instance, the
458 // following is required to be a substring of the selector_ field. 474 // following is required to be a substring of the selector_ field.
459 std::string required_; 475 std::string required_;
460 476
(...skipping 24 matching lines...) Expand all
485 501
486 // Initialize the current thread context with a new instance of ThreadData. 502 // Initialize the current thread context with a new instance of ThreadData.
487 // This is used by all threads that have names, and can be explicitly 503 // This is used by all threads that have names, and can be explicitly
488 // set *before* any births are threads have taken place. It is generally 504 // set *before* any births are threads have taken place. It is generally
489 // only used by the message loop, which has a well defined name. 505 // only used by the message loop, which has a well defined name.
490 static void InitializeThreadContext(const std::string& suggested_name); 506 static void InitializeThreadContext(const std::string& suggested_name);
491 507
492 // Using Thread Local Store, find the current instance for collecting data. 508 // Using Thread Local Store, find the current instance for collecting data.
493 // If an instance does not exist, construct one (and remember it for use on 509 // If an instance does not exist, construct one (and remember it for use on
494 // this thread. 510 // this thread.
495 // If shutdown has already started, and we don't yet have an instance, then 511 // This may return NULL if the system is disabled for any reason.
496 // return null.
497 static ThreadData* Get(); 512 static ThreadData* Get();
498 513
499 // For a given (unescaped) about:tracking query, develop resulting HTML, and 514 // For a given (unescaped) about:tracking query, develop resulting HTML, and
500 // append to output. 515 // append to output.
501 static void WriteHTML(const std::string& query, std::string* output); 516 static void WriteHTML(const std::string& query, std::string* output);
502 517
518 // Constructe a ListValue instance containing all recursive results in our
eroman 2011/10/24 22:23:04 typo construct.
jar (doing other things) 2011/10/27 06:23:35 Done.
519 // process. The caller assumes ownership of the memory in the returned
520 // instance. The |process_type| should become an enum, which corresponds
521 // to all possible process types. I'm using an int as a placeholder.
522 static base::Value* ToValue(int process_type);
eroman 2011/10/24 22:23:04 not sure about this process_type parameter.
jar (doing other things) 2011/10/27 06:23:35 Rephrased as a TODO task.
523
503 // For a given accumulated array of results, use the comparator to sort and 524 // For a given accumulated array of results, use the comparator to sort and
504 // subtotal, writing the results to the output. 525 // subtotal, writing the results to the output.
505 static void WriteHTMLTotalAndSubtotals( 526 static void WriteHTMLTotalAndSubtotals(
506 const DataCollector::Collection& match_array, 527 const DataCollector::Collection& match_array,
507 const Comparator& comparator, std::string* output); 528 const Comparator& comparator, std::string* output);
508 529
509 // In this thread's data, record a new birth. 530 // Find (or create) a place to count births from the given location in this
510 Births* TallyABirth(const Location& location); 531 // thread, and increment that tally.
511
512 // Find a place to record a death on this thread.
513 void TallyADeath(const Births& the_birth,
514 const base::TimeDelta& queue_duration,
515 const base::TimeDelta& duration);
516
517 // Helper methods to only tally if the current thread has tracking active.
518 //
519 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. 532 // TallyABirthIfActive will returns NULL if the birth cannot be tallied.
520 static Births* TallyABirthIfActive(const Location& location); 533 static Births* TallyABirthIfActive(const Location& location);
521 534
522 // Record the end of a timed run of an object. The |the_birth| is the record 535 // Record the end of a timed run of an object. The |birth| is the record for
523 // for the instance, the |time_posted| and |start_of_run| are times of posting 536 // the instance, the |time_posted| and |start_of_run| are times of posting
524 // into a message loop queue, and of starting to perform the run of the task. 537 // into a message loop queue, and of starting to perform the run of the task.
525 // Implied is that the run just (Now()) ended. The current_message_loop is 538 // The |end_of_run| was just obtained by a call to Now() (just after the task
526 // optional, and only used in DEBUG mode (when supplied) to verify that the 539 // finished).
527 // ThreadData has a thread name that does indeed match the given loop's 540 static void TallyADeathIfActive(const Births* birth,
528 // associated thread name (in RELEASE mode, its use is compiled away).
529 static void TallyADeathIfActive(const Births* the_birth,
530 const base::TimeTicks& time_posted, 541 const base::TimeTicks& time_posted,
531 const base::TimeTicks& delayed_start_time, 542 const base::TimeTicks& delayed_start_time,
532 const base::TimeTicks& start_of_run); 543 const base::TimeTicks& start_of_run,
533 544 const base::TimeTicks& end_of_run);
534 // (Thread safe) Get start of list of instances.
535 static ThreadData* first();
536 // Iterate through the null terminated list of instances.
537 ThreadData* next() const { return next_; }
538 545
539 const std::string thread_name() const { return thread_name_; } 546 const std::string thread_name() const { return thread_name_; }
540 547
548 // ---------------------
549 // The following functions should all be private, and are only public because
550 // the collection is done externally. We need to relocate that code from the
551 // collection class into this class, and then all these methods can be made
552 // private.
553 // (Thread safe) Get start of list of all ThreadData instances.
554 static ThreadData* first();
555 // Iterate through the null terminated list of ThreadData instances.
556 ThreadData* next() const { return next_; }
541 // Using our lock, make a copy of the specified maps. These calls may arrive 557 // Using our lock, make a copy of the specified maps. These calls may arrive
542 // from non-local threads, and are used to quickly scan data from all threads 558 // from non-local threads, and are used to quickly scan data from all threads
543 // in order to build an HTML page for about:tracking. 559 // in order to build an HTML page for about:tracking.
544 void SnapshotBirthMap(BirthMap *output) const; 560 void SnapshotBirthMap(BirthMap *output) const;
545 void SnapshotDeathMap(DeathMap *output) const; 561 void SnapshotDeathMap(DeathMap *output) const;
562 // -------- end of should be private methods.
546 563
547 // Hack: asynchronously clear all birth counts and death tallies data values 564 // Hack: asynchronously clear all birth counts and death tallies data values
548 // in all ThreadData instances. The numerical (zeroing) part is done without 565 // in all ThreadData instances. The numerical (zeroing) part is done without
549 // use of a locks or atomics exchanges, and may (for int64 values) produce 566 // use of a locks or atomics exchanges, and may (for int64 values) produce
550 // bogus counts VERY rarely. 567 // bogus counts VERY rarely.
551 static void ResetAllThreadData(); 568 static void ResetAllThreadData();
552 569
553 // Using our lock to protect the iteration, Clear all birth and death data.
554 void Reset();
555
556 // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN, 570 // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN,
557 // based on argument being true or false respectively. 571 // based on argument being true or false respectively.
558 // IF tracking is not compiled in, this function will return false. 572 // IF tracking is not compiled in, this function will return false.
559 static bool StartTracking(bool status); 573 static bool StartTracking(bool status);
560 static bool IsActive(); 574 static bool IsActive();
561 575
562 // Provide a time function that does nothing (runs fast) when we don't have 576 // Provide a time function that does nothing (runs fast) when we don't have
563 // the profiler enabled. It will generally be optimized away when it is 577 // the profiler enabled. It will generally be optimized away when it is
564 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of 578 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of
565 // the code). 579 // the code).
566 static base::TimeTicks Now(); 580 static base::TimeTicks Now();
567 581
568 // WARNING: ONLY call this function when you are running single threaded 582 // WARNING: ONLY call this function when you are running single threaded
569 // (again) and all message loops and threads have terminated. Until that 583 // (again) and all message loops and threads have terminated. Until that
570 // point some threads may still attempt to write into our data structures. 584 // point some threads may still attempt to write into our data structures.
571 // Delete recursively all data structures, starting with the list of 585 // Delete recursively all data structures, starting with the list of
572 // ThreadData instances. 586 // ThreadData instances.
573 static void ShutdownSingleThreadedCleanup(); 587 static void ShutdownSingleThreadedCleanup();
574 588
575 private: 589 private:
576 // Worker thread construction creates a name.
577 ThreadData();
578 // Message loop based construction should provide a name.
579 explicit ThreadData(const std::string& suggested_name);
580
581 ~ThreadData();
582
583 // Enter a new instance into Thread Local Store.
584 // Return the instance, or null if we can't register it (because we're
585 // shutting down).
586 static ThreadData* RegisterCurrentContext(ThreadData* unregistered);
587
588 // Current allowable states of the tracking system. The states always 590 // Current allowable states of the tracking system. The states always
589 // proceed towards SHUTDOWN, and never go backwards. 591 // proceed towards SHUTDOWN, and never go backwards.
590 enum Status { 592 enum Status {
591 UNINITIALIZED, 593 UNINITIALIZED,
592 ACTIVE, 594 ACTIVE,
593 SHUTDOWN, 595 SHUTDOWN,
594 }; 596 };
595 597
598 typedef std::stack<const ThreadData*> ThreadDataPool;
599
600 // Worker thread construction creates a name since there is none.
601 ThreadData();
602 // Message loop based construction should provide a name.
603 explicit ThreadData(const std::string& suggested_name);
604
605 ~ThreadData();
606
607 // Push this instance to the head of all_thread_data_list_head_, linking it to
608 // the previous head. This is performed after each construction, and leaves
609 // the instance permanently on that list.
610 void PushToHeadOfList();
611
612 // In this thread's data, record a new birth.
613 Births* TallyABirth(const Location& location);
614
615 // Find a place to record a death on this thread.
616 void TallyADeath(const Births& birth,
617 const base::TimeDelta& queue_duration,
618 const base::TimeDelta& duration);
619
620 // Using our lock to protect the iteration, Clear all birth and death data.
621 void Reset();
622
623 // This method is called by the TLS system when a thread terminates.
624 // The argument may be NULL if this thread has never tracked a birth or death.
625 static void OnThreadTermination(void* thread_data);
626
627 // This method should be called when a worker thread terminates, so that we
628 // can save all the thread data into a cache of reusable ThreadData instances.
629 void OnThreadTerminationCleanup() const;
630
596 // We use thread local store to identify which ThreadData to interact with. 631 // We use thread local store to identify which ThreadData to interact with.
597 static base::ThreadLocalStorage::Slot tls_index_; 632 static base::ThreadLocalStorage::Slot tls_index_;
598 633
599 // Link to the most recently created instance (starts a null terminated list). 634 // Link to the most recently created instance (starts a null terminated list).
600 static ThreadData* first_; 635 // The list is traversed by about:tracking when it needs to snapshot data.
601 // Protection for access to first_. 636 static ThreadData* all_thread_data_list_head_;
637 // Set of ThreadData instances for use with worker threads. When a worker
638 // thread is done (terminating), we push it into this pool. When a new worker
639 // thread is created, we first try to re-use a ThreadData instance from the
640 // pool, and if none are available, construct a new one.
641 static ThreadDataPool* unregistered_thread_data_pool_;
642 // Protection for access to all_thread_data_list_head_, and to
643 // unregistered_thread_data_pool_.
602 static base::Lock list_lock_; 644 static base::Lock list_lock_;
603 645
604 // We set status_ to SHUTDOWN when we shut down the tracking service. 646 // We set status_ to SHUTDOWN when we shut down the tracking service.
605 static Status status_; 647 static Status status_;
606 648
607 // Link to next instance (null terminated list). Used to globally track all 649 // Link to next instance (null terminated list). Used to globally track all
608 // registered instances (corresponds to all registered threads where we keep 650 // registered instances (corresponds to all registered threads where we keep
609 // data). 651 // data).
610 ThreadData* next_; 652 ThreadData* next_;
611 653
612 // The name of the thread that is being recorded. If this thread has no 654 // The name of the thread that is being recorded. If this thread has no
613 // message_loop, then this is a worker thread, with a sequence number postfix. 655 // message_loop, then this is a worker thread, with a sequence number postfix.
614 std::string thread_name_; 656 std::string thread_name_;
615 657
658 // Indicate if this is a worker thread, and the ThreadData contexts should be
659 // stored in the unregistered_thread_data_pool_ when not in use.
660 bool is_a_worker_thread_;
661
616 // A map used on each thread to keep track of Births on this thread. 662 // A map used on each thread to keep track of Births on this thread.
617 // This map should only be accessed on the thread it was constructed on. 663 // This map should only be accessed on the thread it was constructed on.
618 // When a snapshot is needed, this structure can be locked in place for the 664 // When a snapshot is needed, this structure can be locked in place for the
619 // duration of the snapshotting activity. 665 // duration of the snapshotting activity.
620 BirthMap birth_map_; 666 BirthMap birth_map_;
621 667
622 // Similar to birth_map_, this records informations about death of tracked 668 // Similar to birth_map_, this records informations about death of tracked
623 // instances (i.e., when a tracked instance was destroyed on this thread). 669 // instances (i.e., when a tracked instance was destroyed on this thread).
624 // It is locked before changing, and hence other threads may access it by 670 // It is locked before changing, and hence other threads may access it by
625 // locking before reading it. 671 // locking before reading it.
626 DeathMap death_map_; 672 DeathMap death_map_;
627 673
628 // Lock to protect *some* access to BirthMap and DeathMap. The maps are 674 // Lock to protect *some* access to BirthMap and DeathMap. The maps are
629 // regularly read and written on this thread, but may only be read from other 675 // regularly read and written on this thread, but may only be read from other
630 // threads. To support this, we acquire this lock if we are writing from this 676 // threads. To support this, we acquire this lock if we are writing from this
631 // thread, or reading from another thread. For reading from this thread we 677 // thread, or reading from another thread. For reading from this thread we
632 // don't need a lock, as there is no potential for a conflict since the 678 // don't need a lock, as there is no potential for a conflict since the
633 // writing is only done from this thread. 679 // writing is only done from this thread.
634 mutable base::Lock lock_; 680 mutable base::Lock lock_;
635 681
636 // The next available thread number. This should only be accessed when the 682 // The next available thread number. This should only be accessed when the
637 // list_lock_ is held. 683 // list_lock_ is held.
638 static int thread_number_counter; 684 static int thread_number_counter_;
639 685
640 DISALLOW_COPY_AND_ASSIGN(ThreadData); 686 DISALLOW_COPY_AND_ASSIGN(ThreadData);
641 }; 687 };
642 688
643 //------------------------------------------------------------------------------ 689 //------------------------------------------------------------------------------
644 // Provide simple way to to start global tracking, and to tear down tracking 690 // Provide simple way to to start global tracking, and to tear down tracking
645 // when done. Note that construction and destruction of this object must be 691 // when done. The design has evolved to *not* do any teardown (and just leak
646 // done when running in threaded mode (before spawning a lot of threads 692 // all allocated data structures). As a result, we don't have any code in this
647 // for construction, and after shutting down all the threads for destruction). 693 // destructor, and perhaps this whole class should go away.
648
649 // To prevent grabbing thread local store resources time and again if someone
650 // chooses to try to re-run the browser many times, we maintain global state and
651 // only allow the tracking system to be started up at most once, and shutdown
652 // at most once. See bug 31344 for an example.
653 694
654 class BASE_EXPORT AutoTracking { 695 class BASE_EXPORT AutoTracking {
655 public: 696 public:
656 AutoTracking() { 697 AutoTracking() {
657 if (state_ != kNeverBeenRun) 698 if (state_ != kNeverBeenRun)
658 return; 699 return;
659 ThreadData::StartTracking(true); 700 ThreadData::StartTracking(true);
660 state_ = kRunning; 701 state_ = kRunning;
661 } 702 }
662 703
663 ~AutoTracking() { 704 ~AutoTracking() {
664 #ifndef NDEBUG
665 if (state_ != kRunning)
666 return;
667 // We don't do cleanup of any sort in Release build because it is a
668 // complete waste of time. Since Chromium doesn't join all its thread and
669 // guarantee we're in a single threaded mode, we don't even do cleanup in
670 // debug mode, as it will generate race-checker warnings.
671 #endif
672 } 705 }
673 706
674 private: 707 private:
675 enum State { 708 enum State {
676 kNeverBeenRun, 709 kNeverBeenRun,
677 kRunning, 710 kRunning,
678 kTornDownAndStopped,
679 }; 711 };
680 static State state_; 712 static State state_;
681 713
682 DISALLOW_COPY_AND_ASSIGN(AutoTracking); 714 DISALLOW_COPY_AND_ASSIGN(AutoTracking);
683 }; 715 };
684 716
685
686 } // namespace tracked_objects 717 } // namespace tracked_objects
687 718
688 #endif // BASE_TRACKED_OBJECTS_H_ 719 #endif // BASE_TRACKED_OBJECTS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698