Index: base/tracked_objects.h |
diff --git a/base/tracked_objects.h b/base/tracked_objects.h |
index 511a289066184074110405bb254d568473d8423a..055cf190d5ede89a25a85e5997a9d3e256f17d38 100644 |
--- a/base/tracked_objects.h |
+++ b/base/tracked_objects.h |
@@ -352,6 +352,8 @@ struct BASE_EXPORT TaskSnapshot { |
// harvest data from all existing instances. |
struct ProcessDataSnapshot; |
+class BASE_EXPORT TaskStopwatch; |
+ |
class BASE_EXPORT ThreadData { |
public: |
// Current allowable states of the tracking system. The states can vary |
@@ -403,8 +405,7 @@ class BASE_EXPORT ThreadData { |
// finished). It is provided as an argument to help with testing. |
static void TallyRunOnNamedThreadIfTracking( |
const base::TrackingInfo& completed_task, |
- const TrackedTime& start_of_run, |
- const TrackedTime& end_of_run); |
+ const TaskStopwatch& stopwatch); |
// Record the end of a timed run of an object. The |birth| is the record for |
// the instance, the |time_posted| records that instant, which is presumed to |
@@ -416,15 +417,13 @@ class BASE_EXPORT ThreadData { |
static void TallyRunOnWorkerThreadIfTracking( |
const Births* birth, |
const TrackedTime& time_posted, |
- const TrackedTime& start_of_run, |
- const TrackedTime& end_of_run); |
+ const TaskStopwatch& stopwatch); |
// Record the end of execution in region, generally corresponding to a scope |
// being exited. |
static void TallyRunInAScopedRegionIfTracking( |
const Births* birth, |
- const TrackedTime& start_of_run, |
- const TrackedTime& end_of_run); |
+ const TaskStopwatch& stopwatch); |
const std::string& thread_name() const { return thread_name_; } |
@@ -460,14 +459,12 @@ class BASE_EXPORT ThreadData { |
// on. This is currently a compiled option, atop TrackingStatus(). |
static bool TrackingParentChildStatus(); |
- // Special versions of Now() for getting times at start and end of a tracked |
- // run. They are super fast when tracking is disabled, and have some internal |
- // side effects when we are tracking, so that we can deduce the amount of time |
- // accumulated outside of execution of tracked runs. |
+ // Marks a start of a tracked run. It's super fast when tracking is disabled, |
+ // and has some internal side effects when we are tracking, so that we can |
+ // deduce the amount of time accumulated outside of execution of tracked runs. |
// The task that will be tracked is passed in as |parent| so that parent-child |
// relationships can be (optionally) calculated. |
- static TrackedTime NowForStartOfRun(const Births* parent); |
- static TrackedTime NowForEndOfRun(); |
+ static void PrepareForStartOfRun(const Births* parent); |
// Provide a time function that does nothing (runs fast) when we don't have |
// the profiler enabled. It will generally be optimized away when it is |
@@ -487,6 +484,7 @@ class BASE_EXPORT ThreadData { |
static void EnsureCleanupWasCalled(int major_threads_shutdown_count); |
private: |
+ friend class TaskStopwatch; |
// Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it |
// in production code. |
// TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a |
@@ -523,7 +521,9 @@ class BASE_EXPORT ThreadData { |
Births* TallyABirth(const Location& location); |
// Find a place to record a death on this thread. |
- void TallyADeath(const Births& birth, int32 queue_duration, int32 duration); |
+ void TallyADeath(const Births& birth, |
+ int32 queue_duration, |
+ const TaskStopwatch& stopwatch); |
// Snapshot (under a lock) the profiled data for the tasks in each ThreadData |
// instance. Also updates the |birth_counts| tally for each task to keep |
@@ -582,6 +582,10 @@ class BASE_EXPORT ThreadData { |
// increasing time functcion. |
static NowFunction* now_function_; |
+ // If true, now_function_ returns values that can be used to calculate queue |
+ // time. |
+ static bool now_function_is_time_; |
+ |
// We use thread local store to identify which ThreadData to interact with. |
static base::ThreadLocalStorage::StaticSlot tls_index_; |
@@ -665,9 +669,9 @@ class BASE_EXPORT ThreadData { |
mutable base::Lock map_lock_; |
// The stack of parents that are currently being profiled. This includes only |
- // tasks that have started a timer recently via NowForStartOfRun(), but not |
- // yet concluded with a NowForEndOfRun(). Usually this stack is one deep, but |
- // if a scoped region is profiled, or <sigh> a task runs a nested-message |
+ // tasks that have started a timer recently via PrepareForStartOfRun(), but |
+ // not yet concluded with a NowForEndOfRun(). Usually this stack is one deep, |
+ // but if a scoped region is profiled, or <sigh> a task runs a nested-message |
// loop, then the stack can grow larger. Note that we don't try to deduct |
// time in nested porfiles, as our current timer is based on wall-clock time, |
// and not CPU time (and we're hopeful that nested timing won't be a |
@@ -686,10 +690,74 @@ class BASE_EXPORT ThreadData { |
// incarnations). |
int incarnation_count_for_pool_; |
+ // Most recently started (i.e. most nested) stopwatch on the current thread, |
+ // if it exists; NULL otherwise. |
+ TaskStopwatch* current_stopwatch_; |
+ |
DISALLOW_COPY_AND_ASSIGN(ThreadData); |
}; |
//------------------------------------------------------------------------------ |
+// Stopwatch to measure task run time or simply create a time interval that will |
+// be subtracted from the current most nested task's run time. Stopwatches |
+// coordinate with the stopwatches in which they are nested to avoid |
+// double-counting nested tasks run times. |
+ |
+class BASE_EXPORT TaskStopwatch { |
+ public: |
+ // Starts the stopwatch. |
+ TaskStopwatch(); |
+ ~TaskStopwatch(); |
+ |
+ // Stops stopwatch. |
+ void Stop(); |
+ |
+ // Returns the start time. |
+ TrackedTime StartTime() const; |
+ |
+ // Task's duration is calculated as the wallclock duration between starting |
+ // and stopping this stopwatch, minus the wallclock durations of any other |
+ // instances that are immediately nested in this one, started and stopped on |
+ // this thread during that period. |
+ int32 RunDurationMs() const; |
+ |
+ // Returns tracking info for the current thread. |
+ ThreadData* GetThreadData() const; |
+ |
+ private: |
+ // Time when the stopwatch was started. |
+ TrackedTime start_time_; |
+ |
+ // Wallclock duration of the task. |
+ int32 wallclock_duration_ms_; |
+ |
+ // Tracking info for the current thread. |
+ ThreadData* current_thread_data_; |
+ |
+ // Sum of wallclock durations of all stopwatches that were directly nested in |
+ // this one. |
+ int32 excluded_duration_ms_; |
+ |
+ // Stopwatch which was running on our thread when this stopwatch was started. |
+ // That preexisting stopwatch must be adjusted to the exclude the wallclock |
+ // duration of this stopwatch. |
+ TaskStopwatch* parent_; |
+ |
+#if DCHECK_IS_ON |
+ // State of the stopwatch. Stopwatch is first constructed in a running state, |
+ // then stopped, then destructed. |
+ enum { |
+ RUNNING, |
+ STOPPED |
+ } state_; |
+ |
+ // Currently running stopwatch that is directly nested in this one, if such |
+ // stopwatch exists. NULL otherwise. |
+ TaskStopwatch* child_; |
+#endif |
+}; |
+ |
+//------------------------------------------------------------------------------ |
// A snapshotted representation of a (parent, child) task pair, for tracking |
// hierarchical profiles. |