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

Side by Side Diff: base/tracked_objects.h

Issue 8233037: Update task tracking to not depend on message_loop_ singleton (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
« no previous file with comments | « base/threading/worker_pool_win.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) 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 <string> 10 #include <string>
(...skipping 13 matching lines...) Expand all
24 // very little contention caused by the tracking. The data can be viewed via 24 // 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. 25 // the about:tracking URL, with a variety of sorting and filtering choices.
26 // 26 //
27 // These classes serve as the basis of a profiler of sorts for the Tasks system. 27 // These classes serve as the basis of a profiler of sorts for the Tasks system.
28 // As a result, design decisions were made to maximize speed, by minimizing 28 // As a result, design decisions were made to maximize speed, by minimizing
29 // recurring allocation/deallocation, lock contention and data copying. In the 29 // recurring allocation/deallocation, lock contention and data copying. In the
30 // "stable" state, which is reached relatively quickly, there is no separate 30 // "stable" state, which is reached relatively quickly, there is no separate
31 // marginal allocation cost associated with construction or destruction of 31 // marginal allocation cost associated with construction or destruction of
32 // tracked objects, no locks are generally employed, and probably the largest 32 // tracked objects, no locks are generally employed, and probably the largest
33 // computational cost is associated with obtaining start and stop times for 33 // computational cost is associated with obtaining start and stop times for
34 // instances as they are created and destroyed. The introduction of worker 34 // instances as they are created and destroyed.
35 // threads had a slight impact on this approach, and required use of some locks
36 // when accessing data from the worker threads.
37 // 35 //
38 // The following describes the lifecycle of tracking an instance. 36 // The following describes the lifecycle of tracking an instance.
39 // 37 //
40 // First off, when the instance is created, the FROM_HERE macro is expanded 38 // First off, when the instance is created, the FROM_HERE macro is expanded
41 // to specify the birth place (file, line, function) where the instance was 39 // to specify the birth place (file, line, function) where the instance was
42 // created. That data is used to create a transient Location instance 40 // created. That data is used to create a transient Location instance
43 // encapsulating the above triple of information. The strings (like __FILE__) 41 // encapsulating the above triple of information. The strings (like __FILE__)
44 // are passed around by reference, with the assumption that they are static, and 42 // are passed around by reference, with the assumption that they are static, and
45 // will never go away. This ensures that the strings can be dealt with as atoms 43 // will never go away. This ensures that the strings can be dealt with as atoms
46 // with great efficiency (i.e., copying of strings is never needed, and 44 // with great efficiency (i.e., copying of strings is never needed, and
47 // comparisons for equality can be based on pointer comparisons). 45 // comparisons for equality can be based on pointer comparisons).
48 // 46 //
49 // Next, a Births instance is created for use ONLY on the thread where this 47 // Next, a Births instance is created for use ONLY on the thread where this
50 // instance was created. That Births instance records (in a base class 48 // instance was created. That Births instance records (in a base class
51 // BirthOnThread) references to the static data provided in a Location instance, 49 // BirthOnThread) references to the static data provided in a Location instance,
52 // as well as a pointer specifying the thread on which the birth takes place. 50 // as well as a pointer specifying the thread on which the birth takes place.
53 // Hence there is at most one Births instance for each Location on each thread. 51 // Hence there is at most one Births instance for each Location on each thread.
54 // The derived Births class contains slots for recording statistics about all 52 // The derived Births class contains slots for recording statistics about all
55 // instances born at the same location. Statistics currently include only the 53 // instances born at the same location. Statistics currently include only the
56 // count of instances constructed. 54 // count of instances constructed.
55 //
57 // Since the base class BirthOnThread contains only constant data, it can be 56 // Since the base class BirthOnThread contains only constant data, it can be
58 // freely accessed by any thread at any time (i.e., only the statistic needs to 57 // freely accessed by any thread at any time (i.e., only the statistic needs to
59 // be handled carefully, and it is ONLY read or written by the birth thread). 58 // be handled carefully, and stats are updated exclusively on the birth thread).
60 // 59 //
61 // For Tasks, having now either constructed or found the Births instance 60 // For Tasks, having now either constructed or found the Births instance
62 // described above, a pointer to the Births instance is then recorded into the 61 // described above, a pointer to the Births instance is then recorded into the
63 // PendingTask structure in MessageLoop. This fact alone is very useful in 62 // PendingTask structure in MessageLoop. This fact alone is very useful in
64 // debugging, when there is a question of where an instance came from. In 63 // debugging, when there is a question of where an instance came from. In
65 // addition, the birth time is also recorded and used to later evaluate the 64 // addition, the birth time is also recorded and used to later evaluate the
66 // lifetime duration of the whole Task. As a result of the above embedding, we 65 // lifetime duration of the whole Task. As a result of the above embedding, we
67 // can find out a Task's location of birth, and thread of birth, without using 66 // can find out a Task's location of birth, and thread of birth, without using
68 // any locks, as all that data is constant across the life of the process. 67 // any locks, as all that data is constant across the life of the process.
69 // 68 //
70 // This can also be done for any other object as well by calling 69 // The above work *could* also be done for any other object as well by calling
71 // TallyABirthIfActive() and TallyADeathIfActive() as appropriate. 70 // TallyABirthIfActive() and TallyADeathIfActive() as appropriate.
72 // 71 //
73 // The amount of memory used in the above data structures depends on how many 72 // The amount of memory used in the above data structures depends on how many
74 // threads there are, and how many Locations of construction there are. 73 // threads there are, and how many Locations of construction there are.
75 // Fortunately, we don't use memory that is the product of those two counts, but 74 // Fortunately, we don't use memory that is the product of those two counts, but
76 // rather we only need one Births instance for each thread that constructs an 75 // rather we only need one Births instance for each thread that constructs an
77 // instance at a Location. In many cases, instances are only created on one 76 // instance at a Location. In many cases, instances are only created on one
78 // thread, so the memory utilization is actually fairly restrained. 77 // thread, so the memory utilization is actually fairly restrained.
79 // 78 //
80 // Lastly, when an instance is deleted, the final tallies of statistics are 79 // Lastly, when an instance is deleted, the final tallies of statistics are
81 // carefully accumulated. That tallying wrties into slots (members) in a 80 // carefully accumulated. That tallying wrties into slots (members) in a
82 // collection of DeathData instances. For each birth place Location that is 81 // collection of DeathData instances. For each birth place Location that is
83 // destroyed on a thread, there is a DeathData instance to record the additional 82 // destroyed on a thread, there is a DeathData instance to record the additional
84 // death count, as well as accumulate the lifetime duration of the instance as 83 // death count, as well as accumulate the run-time and queue-time durations for
85 // it is destroyed (dies). By maintaining a single place to aggregate this 84 // the instance as it is destroyed (dies). By maintaining a single place to
86 // addition *only* for the given thread, we avoid the need to lock such 85 // aggregate this running sum *only* for the given thread, we avoid the need to
87 // DeathData instances. 86 // lock such DeathData instances. (i.e., these accumulated stats in a DeathData
87 // instance are exclusively updated by the singular owning thread).
88 // 88 //
89 // With the above lifecycle description complete, the major remaining detail is 89 // With the above lifecycle description complete, the major remaining detail is
90 // explaining how each thread maintains a list of DeathData instances, and of 90 // explaining how each thread maintains a list of DeathData instances, and of
91 // Births instances, and is able to avoid additional (redundant/unnecessary) 91 // Births instances, and is able to avoid additional (redundant/unnecessary)
92 // allocations. 92 // allocations.
93 // 93 //
94 // Each thread maintains a list of data items specific to that thread in a 94 // Each thread maintains a list of data items specific to that thread in a
95 // ThreadData instance (for that specific thread only). The two critical items 95 // ThreadData instance (for that specific thread only). The two critical items
96 // are lists of DeathData and Births instances. These lists are maintained in 96 // 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 97 // STL maps, which are indexed by Location. As noted earlier, we can compare
(...skipping 24 matching lines...) Expand all
122 // For a given birth location, information about births are spread across data 122 // For a given birth location, information about births are spread across data
123 // structures that are asynchronously changing on various threads. For display 123 // structures that are asynchronously changing on various threads. For display
124 // purposes, we need to construct Snapshot instances for each combination of 124 // purposes, we need to construct Snapshot instances for each combination of
125 // birth thread, death thread, and location, along with the count of such 125 // birth thread, death thread, and location, along with the count of such
126 // lifetimes. We gather such data into a Snapshot instances, so that such 126 // lifetimes. We gather such data into a Snapshot instances, so that such
127 // instances can be sorted and aggregated (and remain frozen during our 127 // instances can be sorted and aggregated (and remain frozen during our
128 // processing). Snapshot instances use pointers to constant portions of the 128 // processing). Snapshot instances use pointers to constant portions of the
129 // birth and death datastructures, but have local (frozen) copies of the actual 129 // birth and death datastructures, but have local (frozen) copies of the actual
130 // statistics (birth count, durations, etc. etc.). 130 // statistics (birth count, durations, etc. etc.).
131 // 131 //
132 // A DataCollector is a container object that holds a set of Snapshots. A 132 // A DataCollector is a container object that holds a set of Snapshots. The
133 // DataCollector can be passed from thread to thread, and each thread 133 // statistics in a snapshot are gathered asynhcronously relative to their
134 // contributes to it by adding or updating Snapshot instances. DataCollector 134 // ongoing updates. It is possible, though highly unlikely, that stats such
135 // instances are thread safe containers which are passed to various threads to 135 // as a 64bit counter could incorrectly recorded by this process. The advantage
136 // accumulate all Snapshot instances. 136 // to having fast (non-atomic) updates of the data outweighs the minimal risk
137 // of a singular corrupt statistic snapshot (only the snapshot could be corrupt,
138 // not the underlying and ongoing stistic). In constrast, pointer data that is
139 // accessed during snapshotting is completely invariant, and hence is perfectly
140 // acquired (i.e., no potential corruption, and no risk of a bad memory
141 // reference).
137 // 142 //
138 // After an array of Snapshots instances are colleted into a DataCollector, they 143 // After an array of Snapshots instances are colleted into a DataCollector, they
139 // need to be sorted, and possibly aggregated (example: how many threads are in 144 // need to be prepared for display our output. We currently implement a direct
140 // a specific consecutive set of Snapshots? What was the total birth count for 145 // renderin to HTML, but we will soon also have a JSON serialization as well.
141 // that set? etc.). Aggregation instances collect running sums of any set of 146
142 // snapshot instances, and are used to print sub-totals in an about:tracking 147 // For direct HTML display, the data must be sorted, and possibly aggregated
143 // page. 148 // (example: how many threads are in a specific consecutive set of Snapshots?
149 // What was the total birth count for that set? etc.). Aggregation instances
150 // collect running sums of any set of snapshot instances, and are used to print
151 // sub-totals in an about:tracking page.
144 // 152 //
145 // TODO(jar): I need to store DataCollections, and provide facilities for taking 153 // TODO(jar): I need to store DataCollections, and provide facilities for taking
146 // the difference between two gathered DataCollections. For now, I'm just 154 // the difference between two gathered DataCollections. For now, I'm just
147 // adding a hack that Reset()'s to zero all counts and stats. This is also 155 // adding a hack that Reset()'s to zero all counts and stats. This is also
148 // done in a slighly thread-unsafe fashion, as the reseting is done 156 // done in a slighly thread-unsafe fashion, as the reseting is done
149 // asynchronously relative to ongoing updates, and worse yet, some data fields 157 // asynchronously relative to ongoing updates, and worse yet, some data fields
150 // are 64bit quantities, and are not atomicly accessed (reset or incremented 158 // are 64bit quantities, and are not atomicly accessed (reset or incremented
151 // etc.). For basic profiling, this will work "most of the time," and should be 159 // etc.). For basic profiling, this will work "most of the time," and should be
152 // sufficient... but storing away DataCollections is the "right way" to do this. 160 // sufficient... but storing away DataCollections is the "right way" to do this.
153 161
154 class MessageLoop; 162 class MessageLoop;
155 163
156 namespace tracked_objects { 164 namespace tracked_objects {
157 165
158 //------------------------------------------------------------------------------ 166 //------------------------------------------------------------------------------
159 // For a specific thread, and a specific birth place, the collection of all 167 // For a specific thread, and a specific birth place, the collection of all
160 // death info (with tallies for each death thread, to prevent access conflicts). 168 // death info (with tallies for each death thread, to prevent access conflicts).
161 class ThreadData; 169 class ThreadData;
162 class BASE_EXPORT BirthOnThread { 170 class BASE_EXPORT BirthOnThread {
163 public: 171 public:
164 explicit BirthOnThread(const Location& location); 172 explicit BirthOnThread(const Location& location);
165 173
166 const Location location() const { return location_; } 174 const Location location() const { return location_; }
167 const ThreadData* birth_thread() const { return birth_thread_; } 175 const ThreadData* birth_thread() const { return birth_thread_; }
168 176
169 private: 177 private:
170 // File/lineno of birth. This defines the essence of the type, as the context 178 // File/lineno of birth. This defines the essence of the task, as the context
171 // of the birth (construction) often tell what the item is for. This field 179 // of the birth (construction) often tell what the item is for. This field
172 // is const, and hence safe to access from any thread. 180 // is const, and hence safe to access from any thread.
173 const Location location_; 181 const Location location_;
174 182
175 // The thread that records births into this object. Only this thread is 183 // The thread that records births into this object. Only this thread is
176 // allowed to access birth_count_ (which changes over time). 184 // allowed to access birth_count_ (which changes over time).
177 const ThreadData* birth_thread_; // The thread this birth took place on. 185 const ThreadData* birth_thread_; // The thread this birth took place on.
178 186
179 DISALLOW_COPY_AND_ASSIGN(BirthOnThread); 187 DISALLOW_COPY_AND_ASSIGN(BirthOnThread);
180 }; 188 };
(...skipping 25 matching lines...) Expand all
206 }; 214 };
207 215
208 //------------------------------------------------------------------------------ 216 //------------------------------------------------------------------------------
209 // Basic info summarizing multiple destructions of an object with a single 217 // Basic info summarizing multiple destructions of an object with a single
210 // birthplace (fixed Location). Used both on specific threads, and also used 218 // birthplace (fixed Location). Used both on specific threads, and also used
211 // in snapshots when integrating assembled data. 219 // in snapshots when integrating assembled data.
212 220
213 class BASE_EXPORT DeathData { 221 class BASE_EXPORT DeathData {
214 public: 222 public:
215 // Default initializer. 223 // Default initializer.
216 DeathData() : count_(0), square_duration_(0) {} 224 DeathData() : count_(0) {}
217 225
218 // When deaths have not yet taken place, and we gather data from all the 226 // When deaths have not yet taken place, and we gather data from all the
219 // threads, we create DeathData stats that tally the number of births without 227 // threads, we create DeathData stats that tally the number of births without
220 // a corrosponding death. 228 // a corrosponding death.
221 explicit DeathData(int count) : count_(count), square_duration_(0) {} 229 explicit DeathData(int count) : count_(count) {}
222 230
223 void RecordDeath(const base::TimeDelta& duration); 231 // Update stats for a task destruction (death) that had a Run() time of
232 // |duration|, and has had a queueing delay of |queue_duration|.
233 void RecordDeath(const base::TimeDelta& queue_duration,
234 const base::TimeDelta& run_duration);
224 235
225 // Metrics accessors. 236 // Metrics accessors.
226 int count() const { return count_; } 237 int count() const { return count_; }
227 base::TimeDelta life_duration() const { return life_duration_; } 238 base::TimeDelta run_duration() const { return run_duration_; }
228 int64 square_duration() const { return square_duration_; } 239 int AverageMsRunDuration() const;
229 int AverageMsDuration() const; 240 base::TimeDelta queue_duration() const { return queue_duration_; }
230 double StandardDeviation() const; 241 int AverageMsQueueDuration() const;
231 242
232 // Accumulate metrics from other into this. 243 // Accumulate metrics from other into this. This method is never used on
244 // realtime statistics, and only used in snapshots and aggregatinos.
233 void AddDeathData(const DeathData& other); 245 void AddDeathData(const DeathData& other);
234 246
235 // Simple print of internal state. 247 // Simple print of internal state.
236 void Write(std::string* output) const; 248 void Write(std::string* output) const;
237 249
238 // Reset all tallies to zero. 250 // Reset all tallies to zero. This is used as a hack on realtime data.
239 void Clear(); 251 void Clear();
240 252
241 private: 253 private:
242 int count_; // Number of destructions. 254 int count_; // Number of destructions.
243 base::TimeDelta life_duration_; // Sum of all lifetime durations. 255 base::TimeDelta run_duration_; // Sum of all Run()time durations.
244 int64 square_duration_; // Sum of squares in milliseconds. 256 base::TimeDelta queue_duration_; // Sum of all queue time durations.
245 }; 257 };
246 258
247 //------------------------------------------------------------------------------ 259 //------------------------------------------------------------------------------
248 // A temporary collection of data that can be sorted and summarized. It is 260 // A temporary collection of data that can be sorted and summarized. It is
249 // gathered (carefully) from many threads. Instances are held in arrays and 261 // gathered (carefully) from many threads. Instances are held in arrays and
250 // processed, filtered, and rendered. 262 // processed, filtered, and rendered.
251 // The source of this data was collected on many threads, and is asynchronously 263 // The source of this data was collected on many threads, and is asynchronously
252 // changing. The data in this instance is not asynchronously changing. 264 // changing. The data in this instance is not asynchronously changing.
253 265
254 class BASE_EXPORT Snapshot { 266 class BASE_EXPORT Snapshot {
255 public: 267 public:
256 // When snapshotting a full life cycle set (birth-to-death), use this: 268 // When snapshotting a full life cycle set (birth-to-death), use this:
257 Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread, 269 Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread,
258 const DeathData& death_data); 270 const DeathData& death_data);
259 271
260 // When snapshotting a birth, with no death yet, use this: 272 // When snapshotting a birth, with no death yet, use this:
261 Snapshot(const BirthOnThread& birth_on_thread, int count); 273 Snapshot(const BirthOnThread& birth_on_thread, int count);
262 274
263
264 const ThreadData* birth_thread() const { return birth_->birth_thread(); } 275 const ThreadData* birth_thread() const { return birth_->birth_thread(); }
265 const Location location() const { return birth_->location(); } 276 const Location location() const { return birth_->location(); }
266 const BirthOnThread& birth() const { return *birth_; } 277 const BirthOnThread& birth() const { return *birth_; }
267 const ThreadData* death_thread() const {return death_thread_; } 278 const ThreadData* death_thread() const {return death_thread_; }
268 const DeathData& death_data() const { return death_data_; } 279 const DeathData& death_data() const { return death_data_; }
269 const std::string DeathThreadName() const; 280 const std::string DeathThreadName() const;
270 281
271 int count() const { return death_data_.count(); } 282 int count() const { return death_data_.count(); }
272 base::TimeDelta life_duration() const { return death_data_.life_duration(); } 283 base::TimeDelta run_duration() const { return death_data_.run_duration(); }
273 int64 square_duration() const { return death_data_.square_duration(); } 284 int AverageMsRunDuration() const {
274 int AverageMsDuration() const { return death_data_.AverageMsDuration(); } 285 return death_data_.AverageMsRunDuration();
286 }
287 base::TimeDelta queue_duration() const {
288 return death_data_.queue_duration();
289 }
290 int AverageMsQueueDuration() const {
291 return death_data_.AverageMsQueueDuration();
292 }
275 293
276 void Write(std::string* output) const; 294 void Write(std::string* output) const;
277 295
278 void Add(const Snapshot& other); 296 void Add(const Snapshot& other);
279 297
280 private: 298 private:
281 const BirthOnThread* birth_; // Includes Location and birth_thread. 299 const BirthOnThread* birth_; // Includes Location and birth_thread.
282 const ThreadData* death_thread_; 300 const ThreadData* death_thread_;
283 DeathData death_data_; 301 DeathData death_data_;
284 }; 302 };
303
285 //------------------------------------------------------------------------------ 304 //------------------------------------------------------------------------------
286 // DataCollector is a container class for Snapshot and BirthOnThread count 305 // DataCollector is a container class for Snapshot and BirthOnThread count
287 // items. It protects the gathering under locks, so that it could be called via 306 // items.
288 // Posttask on any threads, or passed to all the target threads in parallel.
289 307
290 class BASE_EXPORT DataCollector { 308 class BASE_EXPORT DataCollector {
291 public: 309 public:
292 typedef std::vector<Snapshot> Collection; 310 typedef std::vector<Snapshot> Collection;
293 311
294 // Construct with a list of how many threads should contribute. This helps us 312 // Construct with a list of how many threads should contribute. This helps us
295 // determine (in the async case) when we are done with all contributions. 313 // determine (in the async case) when we are done with all contributions.
296 DataCollector(); 314 DataCollector();
297 ~DataCollector(); 315 ~DataCollector();
298 316
299 // Add all stats from the indicated thread into our arrays. This function is 317 // Add all stats from the indicated thread into our arrays. This function is
300 // mutex protected, and *could* be called from any threads (although current 318 // mutex protected, and *could* be called from any threads (although current
301 // implementation serialized calls to Append). 319 // implementation serialized calls to Append).
302 void Append(const ThreadData& thread_data); 320 void Append(const ThreadData& thread_data);
303 321
304 // After the accumulation phase, the following accessor is used to process the 322 // After the accumulation phase, the following accessor is used to process the
305 // data. 323 // data.
306 Collection* collection(); 324 Collection* collection();
307 325
308 // After collection of death data is complete, we can add entries for all the 326 // After collection of death data is complete, we can add entries for all the
309 // remaining living objects. 327 // remaining living objects.
310 void AddListOfLivingObjects(); 328 void AddListOfLivingObjects();
311 329
312 private: 330 private:
313 typedef std::map<const BirthOnThread*, int> BirthCount; 331 typedef std::map<const BirthOnThread*, int> BirthCount;
314 332
315 // This instance may be provided to several threads to contribute data. The
316 // following counter tracks how many more threads will contribute. When it is
317 // zero, then all asynchronous contributions are complete, and locked access
318 // is no longer needed.
319 int count_of_contributing_threads_;
320
321 // The array that we collect data into. 333 // The array that we collect data into.
322 Collection collection_; 334 Collection collection_;
323 335
324 // The total number of births recorded at each location for which we have not 336 // The total number of births recorded at each location for which we have not
325 // seen a death count. 337 // seen a death count.
326 BirthCount global_birth_count_; 338 BirthCount global_birth_count_;
327 339
328 base::Lock accumulation_lock_; // Protects access during accumulation phase.
329
330 DISALLOW_COPY_AND_ASSIGN(DataCollector); 340 DISALLOW_COPY_AND_ASSIGN(DataCollector);
331 }; 341 };
332 342
333 //------------------------------------------------------------------------------ 343 //------------------------------------------------------------------------------
334 // Aggregation contains summaries (totals and subtotals) of groups of Snapshot 344 // Aggregation contains summaries (totals and subtotals) of groups of Snapshot
335 // instances to provide printing of these collections on a single line. 345 // instances to provide printing of these collections on a single line.
336 346
337 class BASE_EXPORT Aggregation: public DeathData { 347 class BASE_EXPORT Aggregation: public DeathData {
338 public: 348 public:
339 Aggregation(); 349 Aggregation();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 // use bitfields to accumulate what we have sorted on so far. 384 // use bitfields to accumulate what we have sorted on so far.
375 enum Selector { 385 enum Selector {
376 // Sort orders. 386 // Sort orders.
377 NIL = 0, 387 NIL = 0,
378 BIRTH_THREAD = 1, 388 BIRTH_THREAD = 1,
379 DEATH_THREAD = 2, 389 DEATH_THREAD = 2,
380 BIRTH_FILE = 4, 390 BIRTH_FILE = 4,
381 BIRTH_FUNCTION = 8, 391 BIRTH_FUNCTION = 8,
382 BIRTH_LINE = 16, 392 BIRTH_LINE = 16,
383 COUNT = 32, 393 COUNT = 32,
384 AVERAGE_DURATION = 64, 394 AVERAGE_RUN_DURATION = 64,
385 TOTAL_DURATION = 128, 395 TOTAL_RUN_DURATION = 128,
396 AVERAGE_QUEUE_DURATION = 256,
397 TOTAL_QUEUE_DURATION = 512,
386 398
387 // Imediate action keywords. 399 // Imediate action keywords.
388 RESET_ALL_DATA = -1, 400 RESET_ALL_DATA = -1,
389 }; 401 };
390 402
391 explicit Comparator(); 403 explicit Comparator();
392 404
393 // Reset the comparator to a NIL selector. Clear() and recursively delete any 405 // Reset the comparator to a NIL selector. Clear() and recursively delete any
394 // tiebreaker_ entries. NOTE: We can't use a standard destructor, because 406 // tiebreaker_ entries. NOTE: We can't use a standard destructor, because
395 // the sort algorithm makes copies of this object, and then deletes them, 407 // the sort algorithm makes copies of this object, and then deletes them,
(...skipping 15 matching lines...) Expand all
411 // A comparator can be refined by specifying what to do if the selected basis 423 // A comparator can be refined by specifying what to do if the selected basis
412 // for comparison is insufficient to establish an ordering. This call adds 424 // for comparison is insufficient to establish an ordering. This call adds
413 // the indicated attribute as the new "least significant" basis of comparison. 425 // the indicated attribute as the new "least significant" basis of comparison.
414 void SetTiebreaker(Selector selector, const std::string& required); 426 void SetTiebreaker(Selector selector, const std::string& required);
415 427
416 // Indicate if this instance is set up to sort by the given Selector, thereby 428 // Indicate if this instance is set up to sort by the given Selector, thereby
417 // putting that information in the SortGrouping, so it is not needed in each 429 // putting that information in the SortGrouping, so it is not needed in each
418 // printed line. 430 // printed line.
419 bool IsGroupedBy(Selector selector) const; 431 bool IsGroupedBy(Selector selector) const;
420 432
421 // Using the tiebreakers as set above, we mostly get an ordering, which 433 // Using the tiebreakers as set above, we mostly get an ordering, with some
422 // equivalent groups. If those groups are displayed (rather than just being 434 // equivalent groups. If those groups are displayed (rather than just being
423 // aggregated, then the following is used to order them (within the group). 435 // aggregated, then the following is used to order them (within the group).
424 void SetSubgroupTiebreaker(Selector selector); 436 void SetSubgroupTiebreaker(Selector selector);
425 437
426 // Translate a keyword and restriction in URL path to a selector for sorting. 438 // Translate a keyword and restriction in URL path to a selector for sorting.
427 void ParseKeyphrase(const std::string& key_phrase); 439 void ParseKeyphrase(const std::string& key_phrase);
428 440
429 // Parse a query to decide on sort ordering. 441 // Parse a query to decide on sort ordering.
430 bool ParseQuery(const std::string& query); 442 bool ParseQuery(const std::string& query);
431 443
(...skipping 23 matching lines...) Expand all
455 // criteria. 467 // criteria.
456 int combined_selectors_; 468 int combined_selectors_;
457 469
458 // Some tiebreakrs are for subgroup ordering, and not for basic ordering (in 470 // Some tiebreakrs are for subgroup ordering, and not for basic ordering (in
459 // preparation for aggregation). The subgroup tiebreakers are not consulted 471 // preparation for aggregation). The subgroup tiebreakers are not consulted
460 // when deciding if two items are in equivalent groups. This flag tells us 472 // when deciding if two items are in equivalent groups. This flag tells us
461 // to ignore the tiebreaker when doing Equivalent() testing. 473 // to ignore the tiebreaker when doing Equivalent() testing.
462 bool use_tiebreaker_for_sort_only_; 474 bool use_tiebreaker_for_sort_only_;
463 }; 475 };
464 476
465
466 //------------------------------------------------------------------------------ 477 //------------------------------------------------------------------------------
467 // For each thread, we have a ThreadData that stores all tracking info generated 478 // For each thread, we have a ThreadData that stores all tracking info generated
468 // on this thread. This prevents the need for locking as data accumulates. 479 // on this thread. This prevents the need for locking as data accumulates.
469 480
470 class BASE_EXPORT ThreadData { 481 class BASE_EXPORT ThreadData {
471 public: 482 public:
472 typedef std::map<Location, Births*> BirthMap; 483 typedef std::map<Location, Births*> BirthMap;
473 typedef std::map<const Births*, DeathData> DeathMap; 484 typedef std::map<const Births*, DeathData> DeathMap;
474 485
475 ThreadData(); 486 // Initialize the current thread context with a new instance of ThreadData.
476 ~ThreadData(); 487 // 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
489 // only used by the message loop, which has a well defined name.
490 static void InitializeThreadContext(const std::string& suggested_name);
477 491
478 // Using Thread Local Store, find the current instance for collecting data. 492 // Using Thread Local Store, find the current instance for collecting data.
479 // If an instance does not exist, construct one (and remember it for use on 493 // If an instance does not exist, construct one (and remember it for use on
480 // this thread. 494 // this thread.
481 // If shutdown has already started, and we don't yet have an instance, then 495 // If shutdown has already started, and we don't yet have an instance, then
482 // return null. 496 // return null.
483 static ThreadData* current(); 497 static ThreadData* Get();
484 498
485 // For a given (unescaped) about:tracking query, develop resulting HTML, and 499 // For a given (unescaped) about:tracking query, develop resulting HTML, and
486 // append to output. 500 // append to output.
487 static void WriteHTML(const std::string& query, std::string* output); 501 static void WriteHTML(const std::string& query, std::string* output);
488 502
489 // For a given accumulated array of results, use the comparator to sort and 503 // For a given accumulated array of results, use the comparator to sort and
490 // subtotal, writing the results to the output. 504 // subtotal, writing the results to the output.
491 static void WriteHTMLTotalAndSubtotals( 505 static void WriteHTMLTotalAndSubtotals(
492 const DataCollector::Collection& match_array, 506 const DataCollector::Collection& match_array,
493 const Comparator& comparator, std::string* output); 507 const Comparator& comparator, std::string* output);
494 508
495 // In this thread's data, record a new birth. 509 // In this thread's data, record a new birth.
496 Births* TallyABirth(const Location& location); 510 Births* TallyABirth(const Location& location);
497 511
498 // Find a place to record a death on this thread. 512 // Find a place to record a death on this thread.
499 void TallyADeath(const Births& lifetimes, const base::TimeDelta& duration); 513 void TallyADeath(const Births& the_birth,
514 const base::TimeDelta& queue_duration,
515 const base::TimeDelta& duration);
500 516
501 // Helper methods to only tally if the current thread has tracking active. 517 // Helper methods to only tally if the current thread has tracking active.
502 // 518 //
503 // TallyABirthIfActive will returns NULL if the birth cannot be tallied. 519 // TallyABirthIfActive will returns NULL if the birth cannot be tallied.
504 static Births* TallyABirthIfActive(const Location& location); 520 static Births* TallyABirthIfActive(const Location& location);
505 static void TallyADeathIfActive(const Births* lifetimes, 521
506 const base::TimeDelta& duration); 522 // Record the end of a timed run of an object. The |the_birth| is the record
523 // for 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.
525 // Implied is that the run just (Now()) ended. The current_message_loop is
526 // optional, and only used in DEBUG mode (when supplied) to verify that the
527 // ThreadData has a thread name that does indeed match the given loop's
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,
531 const base::TimeTicks& delayed_start_time,
532 const base::TimeTicks& start_of_run);
507 533
508 // (Thread safe) Get start of list of instances. 534 // (Thread safe) Get start of list of instances.
509 static ThreadData* first(); 535 static ThreadData* first();
510 // Iterate through the null terminated list of instances. 536 // Iterate through the null terminated list of instances.
511 ThreadData* next() const { return next_; } 537 ThreadData* next() const { return next_; }
512 538
513 MessageLoop* message_loop() const { return message_loop_; } 539 const std::string thread_name() const { return thread_name_; }
514 const std::string ThreadName() const;
515 540
516 // Using our lock, make a copy of the specified maps. These calls may arrive 541 // Using our lock, make a copy of the specified maps. These calls may arrive
517 // from non-local threads, and are used to quickly scan data from all threads 542 // from non-local threads, and are used to quickly scan data from all threads
518 // in order to build an HTML page for about:tracking. 543 // in order to build an HTML page for about:tracking.
519 void SnapshotBirthMap(BirthMap *output) const; 544 void SnapshotBirthMap(BirthMap *output) const;
520 void SnapshotDeathMap(DeathMap *output) const; 545 void SnapshotDeathMap(DeathMap *output) const;
521 546
522 // Hack: asynchronously clear all birth counts and death tallies data values 547 // Hack: asynchronously clear all birth counts and death tallies data values
523 // in all ThreadData instances. The numerical (zeroing) part is done without 548 // in all ThreadData instances. The numerical (zeroing) part is done without
524 // use of a locks or atomics exchanges, and may (for int64 values) produce 549 // use of a locks or atomics exchanges, and may (for int64 values) produce
525 // bogus counts VERY rarely. 550 // bogus counts VERY rarely.
526 static void ResetAllThreadData(); 551 static void ResetAllThreadData();
527 552
528 // Using our lock to protect the iteration, Clear all birth and death data. 553 // Using our lock to protect the iteration, Clear all birth and death data.
529 void Reset(); 554 void Reset();
530 555
531 // Using the "known list of threads" gathered during births and deaths, the
532 // following attempts to run the given function once all all such threads.
533 // Note that the function can only be run on threads which have a message
534 // loop!
535 static void RunOnAllThreads(void (*Func)());
536
537 // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN, 556 // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN,
538 // based on argument being true or false respectively. 557 // based on argument being true or false respectively.
539 // IF tracking is not compiled in, this function will return false. 558 // IF tracking is not compiled in, this function will return false.
540 static bool StartTracking(bool status); 559 static bool StartTracking(bool status);
541 static bool IsActive(); 560 static bool IsActive();
542 561
543 #ifdef OS_WIN 562 // Provide a time function that does nothing (runs fast) when we don't have
544 // WARNING: ONLY call this function when all MessageLoops are still intact for 563 // the profiler enabled. It will generally be optimized away when it is
545 // all registered threads. IF you call it later, you will crash. 564 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of
546 // Note: You don't need to call it at all, and you can wait till you are 565 // the code).
547 // single threaded (again) to do the cleanup via 566 static base::TimeTicks Now();
548 // ShutdownSingleThreadedCleanup().
549 // Start the teardown (shutdown) process in a multi-thread mode by disabling
550 // further additions to thread database on all threads. First it makes a
551 // local (locked) change to prevent any more threads from registering. Then
552 // it Posts a Task to all registered threads to be sure they are aware that no
553 // more accumulation can take place.
554 static void ShutdownMultiThreadTracking();
555 #endif
556 567
557 // WARNING: ONLY call this function when you are running single threaded 568 // WARNING: ONLY call this function when you are running single threaded
558 // (again) and all message loops and threads have terminated. Until that 569 // (again) and all message loops and threads have terminated. Until that
559 // point some threads may still attempt to write into our data structures. 570 // point some threads may still attempt to write into our data structures.
560 // Delete recursively all data structures, starting with the list of 571 // Delete recursively all data structures, starting with the list of
561 // ThreadData instances. 572 // ThreadData instances.
562 static void ShutdownSingleThreadedCleanup(); 573 static void ShutdownSingleThreadedCleanup();
563 574
564 private: 575 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
565 // Current allowable states of the tracking system. The states always 588 // Current allowable states of the tracking system. The states always
566 // proceed towards SHUTDOWN, and never go backwards. 589 // proceed towards SHUTDOWN, and never go backwards.
567 enum Status { 590 enum Status {
568 UNINITIALIZED, 591 UNINITIALIZED,
569 ACTIVE, 592 ACTIVE,
570 SHUTDOWN, 593 SHUTDOWN,
571 }; 594 };
572 595
573 #if defined(OS_WIN)
574 class ThreadSafeDownCounter;
575 class RunTheStatic;
576 #endif
577
578 // Each registered thread is called to set status_ to SHUTDOWN.
579 // This is done redundantly on every registered thread because it is not
580 // protected by a mutex. Running on all threads guarantees we get the
581 // notification into the memory cache of all possible threads.
582 static void ShutdownDisablingFurtherTracking();
583
584 // We use thread local store to identify which ThreadData to interact with. 596 // We use thread local store to identify which ThreadData to interact with.
585 static base::ThreadLocalStorage::Slot tls_index_; 597 static base::ThreadLocalStorage::Slot tls_index_;
586 598
587 // Link to the most recently created instance (starts a null terminated list). 599 // Link to the most recently created instance (starts a null terminated list).
588 static ThreadData* first_; 600 static ThreadData* first_;
589 // Protection for access to first_. 601 // Protection for access to first_.
590 static base::Lock list_lock_; 602 static base::Lock list_lock_;
591 603
592 // We set status_ to SHUTDOWN when we shut down the tracking service. This 604 // We set status_ to SHUTDOWN when we shut down the tracking service.
593 // setting is redundantly established by all participating threads so that we
594 // are *guaranteed* (without locking) that all threads can "see" the status
595 // and avoid additional calls into the service.
596 static Status status_; 605 static Status status_;
597 606
598 // Link to next instance (null terminated list). Used to globally track all 607 // Link to next instance (null terminated list). Used to globally track all
599 // registered instances (corresponds to all registered threads where we keep 608 // registered instances (corresponds to all registered threads where we keep
600 // data). 609 // data).
601 ThreadData* next_; 610 ThreadData* next_;
602 611
603 // The message loop where tasks needing to access this instance's private data 612 // The name of the thread that is being recorded. If this thread has no
604 // should be directed. Since some threads have no message loop, some 613 // message_loop, then this is a worker thread, with a sequence number postfix.
605 // instances have data that can't be (safely) modified externally. 614 std::string thread_name_;
606 MessageLoop* message_loop_;
607 615
608 // A map used on each thread to keep track of Births on this thread. 616 // A map used on each thread to keep track of Births on this thread.
609 // This map should only be accessed on the thread it was constructed on. 617 // This map should only be accessed on the thread it was constructed on.
610 // When a snapshot is needed, this structure can be locked in place for the 618 // When a snapshot is needed, this structure can be locked in place for the
611 // duration of the snapshotting activity. 619 // duration of the snapshotting activity.
612 BirthMap birth_map_; 620 BirthMap birth_map_;
613 621
614 // Similar to birth_map_, this records informations about death of tracked 622 // Similar to birth_map_, this records informations about death of tracked
615 // instances (i.e., when a tracked instance was destroyed on this thread). 623 // instances (i.e., when a tracked instance was destroyed on this thread).
616 // It is locked before changing, and hence other threads may access it by 624 // It is locked before changing, and hence other threads may access it by
617 // locking before reading it. 625 // locking before reading it.
618 DeathMap death_map_; 626 DeathMap death_map_;
619 627
620 // Lock to protect *some* access to BirthMap and DeathMap. The maps are 628 // Lock to protect *some* access to BirthMap and DeathMap. The maps are
621 // regularly read and written on this thread, but may only be read from other 629 // regularly read and written on this thread, but may only be read from other
622 // threads. To support this, we acquire this lock if we are writing from this 630 // threads. To support this, we acquire this lock if we are writing from this
623 // thread, or reading from another thread. For reading from this thread we 631 // thread, or reading from another thread. For reading from this thread we
624 // don't need a lock, as there is no potential for a conflict since the 632 // don't need a lock, as there is no potential for a conflict since the
625 // writing is only done from this thread. 633 // writing is only done from this thread.
626 mutable base::Lock lock_; 634 mutable base::Lock lock_;
627 635
636 // The next available thread number. This should only be accessed when the
637 // list_lock_ is held.
638 static int thread_number_counter;
639
628 DISALLOW_COPY_AND_ASSIGN(ThreadData); 640 DISALLOW_COPY_AND_ASSIGN(ThreadData);
629 }; 641 };
630 642
631
632 //------------------------------------------------------------------------------ 643 //------------------------------------------------------------------------------
633 // Provide simple way to to start global tracking, and to tear down tracking 644 // Provide simple way to to start global tracking, and to tear down tracking
634 // when done. Note that construction and destruction of this object must be 645 // when done. Note that construction and destruction of this object must be
635 // done when running in threaded mode (before spawning a lot of threads 646 // done when running in threaded mode (before spawning a lot of threads
636 // for construction, and after shutting down all the threads for destruction). 647 // for construction, and after shutting down all the threads for destruction).
637 648
638 // To prevent grabbing thread local store resources time and again if someone 649 // To prevent grabbing thread local store resources time and again if someone
639 // chooses to try to re-run the browser many times, we maintain global state and 650 // chooses to try to re-run the browser many times, we maintain global state and
640 // only allow the tracking system to be started up at most once, and shutdown 651 // only allow the tracking system to be started up at most once, and shutdown
641 // at most once. See bug 31344 for an example. 652 // at most once. See bug 31344 for an example.
(...skipping 26 matching lines...) Expand all
668 }; 679 };
669 static State state_; 680 static State state_;
670 681
671 DISALLOW_COPY_AND_ASSIGN(AutoTracking); 682 DISALLOW_COPY_AND_ASSIGN(AutoTracking);
672 }; 683 };
673 684
674 685
675 } // namespace tracked_objects 686 } // namespace tracked_objects
676 687
677 #endif // BASE_TRACKED_OBJECTS_H_ 688 #endif // BASE_TRACKED_OBJECTS_H_
OLDNEW
« no previous file with comments | « base/threading/worker_pool_win.cc ('k') | base/tracked_objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698