| OLD | NEW |
| 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> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/base_api.h" | 13 #include "base/base_export.h" |
| 14 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
| 15 #include "base/tracked.h" | 15 #include "base/tracked.h" |
| 16 #include "base/threading/thread_local_storage.h" | 16 #include "base/threading/thread_local_storage.h" |
| 17 | 17 |
| 18 // TrackedObjects provides a database of stats about objects (generally Tasks) | 18 // TrackedObjects provides a database of stats about objects (generally Tasks) |
| 19 // that are tracked. Tracking means their birth, death, duration, birth thread, | 19 // that are tracked. Tracking means their birth, death, duration, birth thread, |
| 20 // death thread, and birth place are recorded. This data is carefully spread | 20 // death thread, and birth place are recorded. This data is carefully spread |
| 21 // across a series of objects so that the counts and times can be rapidly | 21 // across a series of objects so that the counts and times can be rapidly |
| 22 // updated without (usually) having to lock the data, and hence there is usually | 22 // updated without (usually) having to lock the data, and hence there is usually |
| 23 // very little contention caused by the tracking. The data can be viewed via | 23 // very little contention caused by the tracking. The data can be viewed via |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 // | 150 // |
| 151 class MessageLoop; | 151 class MessageLoop; |
| 152 | 152 |
| 153 | 153 |
| 154 namespace tracked_objects { | 154 namespace tracked_objects { |
| 155 | 155 |
| 156 //------------------------------------------------------------------------------ | 156 //------------------------------------------------------------------------------ |
| 157 // For a specific thread, and a specific birth place, the collection of all | 157 // For a specific thread, and a specific birth place, the collection of all |
| 158 // death info (with tallies for each death thread, to prevent access conflicts). | 158 // death info (with tallies for each death thread, to prevent access conflicts). |
| 159 class ThreadData; | 159 class ThreadData; |
| 160 class BASE_API BirthOnThread { | 160 class BASE_EXPORT BirthOnThread { |
| 161 public: | 161 public: |
| 162 explicit BirthOnThread(const Location& location); | 162 explicit BirthOnThread(const Location& location); |
| 163 | 163 |
| 164 const Location location() const { return location_; } | 164 const Location location() const { return location_; } |
| 165 const ThreadData* birth_thread() const { return birth_thread_; } | 165 const ThreadData* birth_thread() const { return birth_thread_; } |
| 166 | 166 |
| 167 private: | 167 private: |
| 168 // File/lineno of birth. This defines the essence of the type, as the context | 168 // File/lineno of birth. This defines the essence of the type, as the context |
| 169 // of the birth (construction) often tell what the item is for. This field | 169 // of the birth (construction) often tell what the item is for. This field |
| 170 // is const, and hence safe to access from any thread. | 170 // is const, and hence safe to access from any thread. |
| 171 const Location location_; | 171 const Location location_; |
| 172 | 172 |
| 173 // The thread that records births into this object. Only this thread is | 173 // The thread that records births into this object. Only this thread is |
| 174 // allowed to access birth_count_ (which changes over time). | 174 // allowed to access birth_count_ (which changes over time). |
| 175 const ThreadData* birth_thread_; // The thread this birth took place on. | 175 const ThreadData* birth_thread_; // The thread this birth took place on. |
| 176 | 176 |
| 177 DISALLOW_COPY_AND_ASSIGN(BirthOnThread); | 177 DISALLOW_COPY_AND_ASSIGN(BirthOnThread); |
| 178 }; | 178 }; |
| 179 | 179 |
| 180 //------------------------------------------------------------------------------ | 180 //------------------------------------------------------------------------------ |
| 181 // A class for accumulating counts of births (without bothering with a map<>). | 181 // A class for accumulating counts of births (without bothering with a map<>). |
| 182 | 182 |
| 183 class BASE_API Births: public BirthOnThread { | 183 class BASE_EXPORT Births: public BirthOnThread { |
| 184 public: | 184 public: |
| 185 explicit Births(const Location& location); | 185 explicit Births(const Location& location); |
| 186 | 186 |
| 187 int birth_count() const { return birth_count_; } | 187 int birth_count() const { return birth_count_; } |
| 188 | 188 |
| 189 // When we have a birth we update the count for this BirhPLace. | 189 // When we have a birth we update the count for this BirhPLace. |
| 190 void RecordBirth() { ++birth_count_; } | 190 void RecordBirth() { ++birth_count_; } |
| 191 | 191 |
| 192 // When a birthplace is changed (updated), we need to decrement the counter | 192 // When a birthplace is changed (updated), we need to decrement the counter |
| 193 // for the old instance. | 193 // for the old instance. |
| 194 void ForgetBirth() { --birth_count_; } // We corrected a birth place. | 194 void ForgetBirth() { --birth_count_; } // We corrected a birth place. |
| 195 | 195 |
| 196 // Hack to quickly reset all counts to zero. | 196 // Hack to quickly reset all counts to zero. |
| 197 void Clear() { birth_count_ = 0; } | 197 void Clear() { birth_count_ = 0; } |
| 198 | 198 |
| 199 private: | 199 private: |
| 200 // The number of births on this thread for our location_. | 200 // The number of births on this thread for our location_. |
| 201 int birth_count_; | 201 int birth_count_; |
| 202 | 202 |
| 203 DISALLOW_COPY_AND_ASSIGN(Births); | 203 DISALLOW_COPY_AND_ASSIGN(Births); |
| 204 }; | 204 }; |
| 205 | 205 |
| 206 //------------------------------------------------------------------------------ | 206 //------------------------------------------------------------------------------ |
| 207 // Basic info summarizing multiple destructions of an object with a single | 207 // Basic info summarizing multiple destructions of an object with a single |
| 208 // birthplace (fixed Location). Used both on specific threads, and also used | 208 // birthplace (fixed Location). Used both on specific threads, and also used |
| 209 // in snapshots when integrating assembled data. | 209 // in snapshots when integrating assembled data. |
| 210 | 210 |
| 211 class BASE_API DeathData { | 211 class BASE_EXPORT DeathData { |
| 212 public: | 212 public: |
| 213 // Default initializer. | 213 // Default initializer. |
| 214 DeathData() : count_(0), square_duration_(0) {} | 214 DeathData() : count_(0), square_duration_(0) {} |
| 215 | 215 |
| 216 // When deaths have not yet taken place, and we gather data from all the | 216 // When deaths have not yet taken place, and we gather data from all the |
| 217 // threads, we create DeathData stats that tally the number of births without | 217 // threads, we create DeathData stats that tally the number of births without |
| 218 // a corrosponding death. | 218 // a corrosponding death. |
| 219 explicit DeathData(int count) : count_(count), square_duration_(0) {} | 219 explicit DeathData(int count) : count_(count), square_duration_(0) {} |
| 220 | 220 |
| 221 void RecordDeath(const base::TimeDelta& duration); | 221 void RecordDeath(const base::TimeDelta& duration); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 242 int64 square_duration_; // Sum of squares in milliseconds. | 242 int64 square_duration_; // Sum of squares in milliseconds. |
| 243 }; | 243 }; |
| 244 | 244 |
| 245 //------------------------------------------------------------------------------ | 245 //------------------------------------------------------------------------------ |
| 246 // A temporary collection of data that can be sorted and summarized. It is | 246 // A temporary collection of data that can be sorted and summarized. It is |
| 247 // gathered (carefully) from many threads. Instances are held in arrays and | 247 // gathered (carefully) from many threads. Instances are held in arrays and |
| 248 // processed, filtered, and rendered. | 248 // processed, filtered, and rendered. |
| 249 // The source of this data was collected on many threads, and is asynchronously | 249 // The source of this data was collected on many threads, and is asynchronously |
| 250 // changing. The data in this instance is not asynchronously changing. | 250 // changing. The data in this instance is not asynchronously changing. |
| 251 | 251 |
| 252 class BASE_API Snapshot { | 252 class BASE_EXPORT Snapshot { |
| 253 public: | 253 public: |
| 254 // When snapshotting a full life cycle set (birth-to-death), use this: | 254 // When snapshotting a full life cycle set (birth-to-death), use this: |
| 255 Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread, | 255 Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread, |
| 256 const DeathData& death_data); | 256 const DeathData& death_data); |
| 257 | 257 |
| 258 // When snapshotting a birth, with no death yet, use this: | 258 // When snapshotting a birth, with no death yet, use this: |
| 259 Snapshot(const BirthOnThread& birth_on_thread, int count); | 259 Snapshot(const BirthOnThread& birth_on_thread, int count); |
| 260 | 260 |
| 261 | 261 |
| 262 const ThreadData* birth_thread() const { return birth_->birth_thread(); } | 262 const ThreadData* birth_thread() const { return birth_->birth_thread(); } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 278 private: | 278 private: |
| 279 const BirthOnThread* birth_; // Includes Location and birth_thread. | 279 const BirthOnThread* birth_; // Includes Location and birth_thread. |
| 280 const ThreadData* death_thread_; | 280 const ThreadData* death_thread_; |
| 281 DeathData death_data_; | 281 DeathData death_data_; |
| 282 }; | 282 }; |
| 283 //------------------------------------------------------------------------------ | 283 //------------------------------------------------------------------------------ |
| 284 // DataCollector is a container class for Snapshot and BirthOnThread count | 284 // DataCollector is a container class for Snapshot and BirthOnThread count |
| 285 // items. It protects the gathering under locks, so that it could be called via | 285 // items. It protects the gathering under locks, so that it could be called via |
| 286 // Posttask on any threads, or passed to all the target threads in parallel. | 286 // Posttask on any threads, or passed to all the target threads in parallel. |
| 287 | 287 |
| 288 class BASE_API DataCollector { | 288 class BASE_EXPORT DataCollector { |
| 289 public: | 289 public: |
| 290 typedef std::vector<Snapshot> Collection; | 290 typedef std::vector<Snapshot> Collection; |
| 291 | 291 |
| 292 // Construct with a list of how many threads should contribute. This helps us | 292 // Construct with a list of how many threads should contribute. This helps us |
| 293 // determine (in the async case) when we are done with all contributions. | 293 // determine (in the async case) when we are done with all contributions. |
| 294 DataCollector(); | 294 DataCollector(); |
| 295 ~DataCollector(); | 295 ~DataCollector(); |
| 296 | 296 |
| 297 // Add all stats from the indicated thread into our arrays. This function is | 297 // Add all stats from the indicated thread into our arrays. This function is |
| 298 // mutex protected, and *could* be called from any threads (although current | 298 // mutex protected, and *could* be called from any threads (although current |
| (...skipping 26 matching lines...) Expand all Loading... |
| 325 | 325 |
| 326 base::Lock accumulation_lock_; // Protects access during accumulation phase. | 326 base::Lock accumulation_lock_; // Protects access during accumulation phase. |
| 327 | 327 |
| 328 DISALLOW_COPY_AND_ASSIGN(DataCollector); | 328 DISALLOW_COPY_AND_ASSIGN(DataCollector); |
| 329 }; | 329 }; |
| 330 | 330 |
| 331 //------------------------------------------------------------------------------ | 331 //------------------------------------------------------------------------------ |
| 332 // Aggregation contains summaries (totals and subtotals) of groups of Snapshot | 332 // Aggregation contains summaries (totals and subtotals) of groups of Snapshot |
| 333 // instances to provide printing of these collections on a single line. | 333 // instances to provide printing of these collections on a single line. |
| 334 | 334 |
| 335 class BASE_API Aggregation: public DeathData { | 335 class BASE_EXPORT Aggregation: public DeathData { |
| 336 public: | 336 public: |
| 337 Aggregation(); | 337 Aggregation(); |
| 338 ~Aggregation(); | 338 ~Aggregation(); |
| 339 | 339 |
| 340 void AddDeathSnapshot(const Snapshot& snapshot); | 340 void AddDeathSnapshot(const Snapshot& snapshot); |
| 341 void AddBirths(const Births& births); | 341 void AddBirths(const Births& births); |
| 342 void AddBirth(const BirthOnThread& birth); | 342 void AddBirth(const BirthOnThread& birth); |
| 343 void AddBirthPlace(const Location& location); | 343 void AddBirthPlace(const Location& location); |
| 344 void Write(std::string* output) const; | 344 void Write(std::string* output) const; |
| 345 void Clear(); | 345 void Clear(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 357 | 357 |
| 358 //------------------------------------------------------------------------------ | 358 //------------------------------------------------------------------------------ |
| 359 // Comparator is a class that supports the comparison of Snapshot instances. | 359 // Comparator is a class that supports the comparison of Snapshot instances. |
| 360 // An instance is actually a list of chained Comparitors, that can provide for | 360 // An instance is actually a list of chained Comparitors, that can provide for |
| 361 // arbitrary ordering. The path portion of an about:tasks URL is translated | 361 // arbitrary ordering. The path portion of an about:tasks URL is translated |
| 362 // into such a chain, which is then used to order Snapshot instances in a | 362 // into such a chain, which is then used to order Snapshot instances in a |
| 363 // vector. It orders them into groups (for aggregation), and can also order | 363 // vector. It orders them into groups (for aggregation), and can also order |
| 364 // instances within the groups (for detailed rendering of the instances in an | 364 // instances within the groups (for detailed rendering of the instances in an |
| 365 // aggregation). | 365 // aggregation). |
| 366 | 366 |
| 367 class BASE_API Comparator { | 367 class BASE_EXPORT Comparator { |
| 368 public: | 368 public: |
| 369 // Selector enum is the token identifier for each parsed keyword, most of | 369 // Selector enum is the token identifier for each parsed keyword, most of |
| 370 // which specify a sort order. | 370 // which specify a sort order. |
| 371 // Since it is not meaningful to sort more than once on a specific key, we | 371 // Since it is not meaningful to sort more than once on a specific key, we |
| 372 // use bitfields to accumulate what we have sorted on so far. | 372 // use bitfields to accumulate what we have sorted on so far. |
| 373 enum Selector { | 373 enum Selector { |
| 374 // Sort orders. | 374 // Sort orders. |
| 375 NIL = 0, | 375 NIL = 0, |
| 376 BIRTH_THREAD = 1, | 376 BIRTH_THREAD = 1, |
| 377 DEATH_THREAD = 2, | 377 DEATH_THREAD = 2, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 // when deciding if two items are in equivalent groups. This flag tells us | 458 // when deciding if two items are in equivalent groups. This flag tells us |
| 459 // to ignore the tiebreaker when doing Equivalent() testing. | 459 // to ignore the tiebreaker when doing Equivalent() testing. |
| 460 bool use_tiebreaker_for_sort_only_; | 460 bool use_tiebreaker_for_sort_only_; |
| 461 }; | 461 }; |
| 462 | 462 |
| 463 | 463 |
| 464 //------------------------------------------------------------------------------ | 464 //------------------------------------------------------------------------------ |
| 465 // For each thread, we have a ThreadData that stores all tracking info generated | 465 // For each thread, we have a ThreadData that stores all tracking info generated |
| 466 // on this thread. This prevents the need for locking as data accumulates. | 466 // on this thread. This prevents the need for locking as data accumulates. |
| 467 | 467 |
| 468 class BASE_API ThreadData { | 468 class BASE_EXPORT ThreadData { |
| 469 public: | 469 public: |
| 470 typedef std::map<Location, Births*> BirthMap; | 470 typedef std::map<Location, Births*> BirthMap; |
| 471 typedef std::map<const Births*, DeathData> DeathMap; | 471 typedef std::map<const Births*, DeathData> DeathMap; |
| 472 | 472 |
| 473 ThreadData(); | 473 ThreadData(); |
| 474 ~ThreadData(); | 474 ~ThreadData(); |
| 475 | 475 |
| 476 // Using Thread Local Store, find the current instance for collecting data. | 476 // Using Thread Local Store, find the current instance for collecting data. |
| 477 // If an instance does not exist, construct one (and remember it for use on | 477 // If an instance does not exist, construct one (and remember it for use on |
| 478 // this thread. | 478 // this thread. |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 // Provide simple way to to start global tracking, and to tear down tracking | 631 // Provide simple way to to start global tracking, and to tear down tracking |
| 632 // when done. Note that construction and destruction of this object must be | 632 // when done. Note that construction and destruction of this object must be |
| 633 // done when running in threaded mode (before spawning a lot of threads | 633 // done when running in threaded mode (before spawning a lot of threads |
| 634 // for construction, and after shutting down all the threads for destruction). | 634 // for construction, and after shutting down all the threads for destruction). |
| 635 | 635 |
| 636 // To prevent grabbing thread local store resources time and again if someone | 636 // To prevent grabbing thread local store resources time and again if someone |
| 637 // chooses to try to re-run the browser many times, we maintain global state and | 637 // chooses to try to re-run the browser many times, we maintain global state and |
| 638 // only allow the tracking system to be started up at most once, and shutdown | 638 // only allow the tracking system to be started up at most once, and shutdown |
| 639 // at most once. See bug 31344 for an example. | 639 // at most once. See bug 31344 for an example. |
| 640 | 640 |
| 641 class BASE_API AutoTracking { | 641 class BASE_EXPORT AutoTracking { |
| 642 public: | 642 public: |
| 643 AutoTracking() { | 643 AutoTracking() { |
| 644 if (state_ != kNeverBeenRun) | 644 if (state_ != kNeverBeenRun) |
| 645 return; | 645 return; |
| 646 ThreadData::StartTracking(true); | 646 ThreadData::StartTracking(true); |
| 647 state_ = kRunning; | 647 state_ = kRunning; |
| 648 } | 648 } |
| 649 | 649 |
| 650 ~AutoTracking() { | 650 ~AutoTracking() { |
| 651 #ifndef NDEBUG | 651 #ifndef NDEBUG |
| (...skipping 14 matching lines...) Expand all Loading... |
| 666 }; | 666 }; |
| 667 static State state_; | 667 static State state_; |
| 668 | 668 |
| 669 DISALLOW_COPY_AND_ASSIGN(AutoTracking); | 669 DISALLOW_COPY_AND_ASSIGN(AutoTracking); |
| 670 }; | 670 }; |
| 671 | 671 |
| 672 | 672 |
| 673 } // namespace tracked_objects | 673 } // namespace tracked_objects |
| 674 | 674 |
| 675 #endif // BASE_TRACKED_OBJECTS_H_ | 675 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |