| 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 <stack> | 10 #include <stack> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/base_export.h" | 14 #include "base/base_export.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/profiler/tracked_time.h" |
| 16 #include "base/time.h" | 17 #include "base/time.h" |
| 17 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
| 18 #include "base/threading/thread_local_storage.h" | 19 #include "base/threading/thread_local_storage.h" |
| 19 #include "base/tracking_info.h" | 20 #include "base/tracking_info.h" |
| 20 #include "base/values.h" | 21 #include "base/values.h" |
| 21 | 22 |
| 22 #if defined(OS_WIN) | |
| 23 #include <mmsystem.h> // Declare timeGetTime(); | |
| 24 #endif | |
| 25 | |
| 26 // TrackedObjects provides a database of stats about objects (generally Tasks) | 23 // TrackedObjects provides a database of stats about objects (generally Tasks) |
| 27 // that are tracked. Tracking means their birth, death, duration, birth thread, | 24 // that are tracked. Tracking means their birth, death, duration, birth thread, |
| 28 // death thread, and birth place are recorded. This data is carefully spread | 25 // death thread, and birth place are recorded. This data is carefully spread |
| 29 // across a series of objects so that the counts and times can be rapidly | 26 // across a series of objects so that the counts and times can be rapidly |
| 30 // updated without (usually) having to lock the data, and hence there is usually | 27 // updated without (usually) having to lock the data, and hence there is usually |
| 31 // very little contention caused by the tracking. The data can be viewed via | 28 // very little contention caused by the tracking. The data can be viewed via |
| 32 // the about:tracking URL, with a variety of sorting and filtering choices. | 29 // the about:tracking URL, with a variety of sorting and filtering choices. |
| 33 // | 30 // |
| 34 // These classes serve as the basis of a profiler of sorts for the Tasks system. | 31 // These classes serve as the basis of a profiler of sorts for the Tasks system. |
| 35 // As a result, design decisions were made to maximize speed, by minimizing | 32 // As a result, design decisions were made to maximize speed, by minimizing |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 // asynchronously relative to ongoing updates, and worse yet, some data fields | 162 // asynchronously relative to ongoing updates, and worse yet, some data fields |
| 166 // are 64bit quantities, and are not atomicly accessed (reset or incremented | 163 // are 64bit quantities, and are not atomicly accessed (reset or incremented |
| 167 // etc.). For basic profiling, this will work "most of the time," and should be | 164 // etc.). For basic profiling, this will work "most of the time," and should be |
| 168 // sufficient... but storing away DataCollections is the "right way" to do this. | 165 // sufficient... but storing away DataCollections is the "right way" to do this. |
| 169 | 166 |
| 170 class MessageLoop; | 167 class MessageLoop; |
| 171 | 168 |
| 172 namespace tracked_objects { | 169 namespace tracked_objects { |
| 173 | 170 |
| 174 //------------------------------------------------------------------------------ | 171 //------------------------------------------------------------------------------ |
| 175 | |
| 176 #define USE_FAST_TIME_CLASS_FOR_DURATION_CALCULATIONS | |
| 177 | |
| 178 #if defined(USE_FAST_TIME_CLASS_FOR_DURATION_CALCULATIONS) | |
| 179 | |
| 180 // TimeTicks maintains a wasteful 64 bits of data (we need less than 32), and on | |
| 181 // windows, a 64 bit timer is expensive to even obtain. We use a simple | |
| 182 // millisecond counter for most of our time values, as well as millisecond units | |
| 183 // of duration between those values. This means we can only handle durations | |
| 184 // up to 49 days (range), or 24 days (non-negative time durations). | |
| 185 // We only define enough methods to service the needs of the tracking classes, | |
| 186 // and our interfaces are modeled after what TimeTicks and TimeDelta use (so we | |
| 187 // can swap them into place if we want to use the "real" classes). | |
| 188 | |
| 189 class BASE_EXPORT Duration { // Similar to base::TimeDelta. | |
| 190 public: | |
| 191 Duration() : ms_(0) {} | |
| 192 | |
| 193 Duration& operator+=(const Duration& other) { | |
| 194 ms_ += other.ms_; | |
| 195 return *this; | |
| 196 } | |
| 197 | |
| 198 Duration operator+(const Duration& other) const { | |
| 199 return Duration(ms_ + other.ms_); | |
| 200 } | |
| 201 | |
| 202 bool operator==(const Duration& other) const { return ms_ == other.ms_; } | |
| 203 bool operator!=(const Duration& other) const { return ms_ != other.ms_; } | |
| 204 bool operator>(const Duration& other) const { return ms_ > other.ms_; } | |
| 205 | |
| 206 static Duration FromMilliseconds(int ms) { return Duration(ms); } | |
| 207 | |
| 208 int32 InMilliseconds() const { return ms_; } | |
| 209 | |
| 210 private: | |
| 211 friend class TrackedTime; | |
| 212 explicit Duration(int32 duration) : ms_(duration) {} | |
| 213 | |
| 214 // Internal time is stored directly in milliseconds. | |
| 215 int32 ms_; | |
| 216 }; | |
| 217 | |
| 218 class BASE_EXPORT TrackedTime { // Similar to base::TimeTicks. | |
| 219 public: | |
| 220 TrackedTime() : ms_(0) {} | |
| 221 explicit TrackedTime(const base::TimeTicks& time) | |
| 222 : ms_((time - base::TimeTicks()).InMilliseconds()) { | |
| 223 } | |
| 224 | |
| 225 static TrackedTime Now() { | |
| 226 #if defined(OS_WIN) | |
| 227 // Use lock-free accessor to 32 bit time. | |
| 228 // Note that TimeTicks::Now() is built on this, so we have "compatible" | |
| 229 // times when we down-convert a TimeTicks sample. | |
| 230 // TODO(jar): Surface this interface via something in base/time.h. | |
| 231 return TrackedTime(static_cast<int32>(::timeGetTime())); | |
| 232 #else | |
| 233 // Posix has nice cheap 64 bit times, so we just down-convert it. | |
| 234 return TrackedTime(base::TimeTicks::Now()); | |
| 235 #endif // OS_WIN | |
| 236 } | |
| 237 | |
| 238 Duration operator-(const TrackedTime& other) const { | |
| 239 return Duration(ms_ - other.ms_); | |
| 240 } | |
| 241 | |
| 242 TrackedTime operator+(const Duration& other) const { | |
| 243 return TrackedTime(ms_ + other.ms_); | |
| 244 } | |
| 245 | |
| 246 bool is_null() const { return ms_ == 0; } | |
| 247 | |
| 248 private: | |
| 249 friend class Duration; | |
| 250 explicit TrackedTime(int32 ms) : ms_(ms) {} | |
| 251 | |
| 252 // Internal duration is stored directly in milliseconds. | |
| 253 uint32 ms_; | |
| 254 }; | |
| 255 | |
| 256 #else | |
| 257 | |
| 258 // Just use full 64 bit time calculations, and the slower TimeTicks::Now(). | |
| 259 typedef base::TimeTicks TrackedTime; | |
| 260 typedef base::TimeDelta Duration; | |
| 261 | |
| 262 #endif // USE_FAST_TIME_CLASS_FOR_DURATION_CALCULATIONS | |
| 263 | |
| 264 //------------------------------------------------------------------------------ | |
| 265 // For a specific thread, and a specific birth place, the collection of all | 172 // For a specific thread, and a specific birth place, the collection of all |
| 266 // death info (with tallies for each death thread, to prevent access conflicts). | 173 // death info (with tallies for each death thread, to prevent access conflicts). |
| 267 class ThreadData; | 174 class ThreadData; |
| 268 class BASE_EXPORT BirthOnThread { | 175 class BASE_EXPORT BirthOnThread { |
| 269 public: | 176 public: |
| 270 BirthOnThread(const Location& location, const ThreadData& current); | 177 BirthOnThread(const Location& location, const ThreadData& current); |
| 271 | 178 |
| 272 const Location location() const { return location_; } | 179 const Location location() const { return location_; } |
| 273 const ThreadData* birth_thread() const { return birth_thread_; } | 180 const ThreadData* birth_thread() const { return birth_thread_; } |
| 274 | 181 |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 // The |start_of_run| is when the worker thread started to perform the run of | 612 // The |start_of_run| is when the worker thread started to perform the run of |
| 706 // the task. | 613 // the task. |
| 707 // The |end_of_run| was just obtained by a call to Now() (just after the task | 614 // The |end_of_run| was just obtained by a call to Now() (just after the task |
| 708 // finished). | 615 // finished). |
| 709 static void TallyRunOnWorkerThreadIfTracking( | 616 static void TallyRunOnWorkerThreadIfTracking( |
| 710 const Births* birth, | 617 const Births* birth, |
| 711 const TrackedTime& time_posted, | 618 const TrackedTime& time_posted, |
| 712 const TrackedTime& start_of_run, | 619 const TrackedTime& start_of_run, |
| 713 const TrackedTime& end_of_run); | 620 const TrackedTime& end_of_run); |
| 714 | 621 |
| 622 // Record the end of execution in region, generally corresponding to a scope |
| 623 // being exited. |
| 624 static void TallyRunInAScopedRegionIfTracking( |
| 625 const Births* birth, |
| 626 const TrackedTime& start_of_run, |
| 627 const TrackedTime& end_of_run); |
| 628 |
| 715 const std::string thread_name() const { return thread_name_; } | 629 const std::string thread_name() const { return thread_name_; } |
| 716 | 630 |
| 717 // --------------------- | 631 // --------------------- |
| 632 // TODO(jar): |
| 718 // The following functions should all be private, and are only public because | 633 // The following functions should all be private, and are only public because |
| 719 // the collection is done externally. We need to relocate that code from the | 634 // the collection is done externally. We need to relocate that code from the |
| 720 // collection class into this class, and then all these methods can be made | 635 // collection class into this class, and then all these methods can be made |
| 721 // private. | 636 // private. |
| 722 // (Thread safe) Get start of list of all ThreadData instances. | 637 // (Thread safe) Get start of list of all ThreadData instances. |
| 723 static ThreadData* first(); | 638 static ThreadData* first(); |
| 724 // Iterate through the null terminated list of ThreadData instances. | 639 // Iterate through the null terminated list of ThreadData instances. |
| 725 ThreadData* next() const { return next_; } | 640 ThreadData* next() const { return next_; } |
| 726 // Using our lock, make a copy of the specified maps. These calls may arrive | 641 // Using our lock, make a copy of the specified maps. These calls may arrive |
| 727 // from non-local threads, and are used to quickly scan data from all threads | 642 // from non-local threads, and are used to quickly scan data from all threads |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 } | 801 } |
| 887 | 802 |
| 888 private: | 803 private: |
| 889 | 804 |
| 890 DISALLOW_COPY_AND_ASSIGN(AutoTracking); | 805 DISALLOW_COPY_AND_ASSIGN(AutoTracking); |
| 891 }; | 806 }; |
| 892 | 807 |
| 893 } // namespace tracked_objects | 808 } // namespace tracked_objects |
| 894 | 809 |
| 895 #endif // BASE_TRACKED_OBJECTS_H_ | 810 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |