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 |