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

Side by Side Diff: base/debug/trace_event_synthetic_delay.h

Issue 53923005: Add synthetic delay testing framework (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Renaming and cleanup. Created 7 years, 1 month 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // The synthetic delay framework makes it possible to dynamically inject
6 // arbitrary delays into into different parts of the codebase. This can be used,
7 // for instance, for testing various task scheduling algorithms.
8 //
9 // The delays are specified in terms of a target duration for a given block of
10 // code. If the code executes faster than the duration, the thread is made to
11 // sleep until the deadline is met.
12 //
13 // Code can be instrumented for delays with two sets of macros. First, for
14 // delays that should apply within a scope, use the following macro:
15 //
16 // TRACE_EVENT_SYNTHETIC_DELAY("cc.LayerTreeHost.DrawAndSwap");
nduca 2013/11/24 19:36:41 i guess it seems possiblein the future that we'll
17 //
18 // For delaying operations that span multiple scopes, use:
19 //
20 // TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE("cc.Scheduler.BeginMainFrame");
21 // ...
22 // TRACE_EVENT_SYNTHETIC_DELAY_APPLY("cc.Scheduler.BeginMainFrame");
23 //
24 // Here ACTIVATE establishes the start time for the delay and APPLY executes the
25 // delay based on the remaining time. ACTIVATE may be called one or multiple
26 // times before APPLY. Only the first call will have an effect. If ACTIVATE
27 // hasn't been called since the last call to APPLY, APPLY will be a no-op.
28 //
29 // Note that while the same delay can be applied in several threads
30 // simultaneously, a single delay operation cannot begin on one thread and end
31 // on another.
32
33 #ifndef BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
34 #define BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
35
36 #include "base/atomicops.h"
37 #include "base/debug/trace_event.h"
38 #include "base/memory/scoped_ptr.h"
39 #include "base/synchronization/lock.h"
40 #include "base/threading/thread_local.h"
41 #include "base/time/time.h"
42
43 // Apply a named delay in the current scope.
44 #define TRACE_EVENT_SYNTHETIC_DELAY(name) \
45 static base::subtle::AtomicWord INTERNAL_TRACE_EVENT_UID(impl_ptr) = 0; \
46 trace_event_internal::ScopedSyntheticDelay INTERNAL_TRACE_EVENT_UID(delay)( \
47 name, &INTERNAL_TRACE_EVENT_UID(impl_ptr));
48
49 // Activate a named delay, establishing its timing start point. May be called
50 // multiple times, but only the first call will have an effect.
51 #define TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE(name) \
52 do { \
53 static base::subtle::AtomicWord impl_ptr = 0; \
54 trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Activate(); \
55 } while (false)
56
57 // Apply a named delay. If TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE was called for
58 // the same delay, that point in time is used as the delay start point. If not,
59 // this call will be a no-op.
60 #define TRACE_EVENT_SYNTHETIC_DELAY_APPLY(name) \
61 do { \
62 static base::subtle::AtomicWord impl_ptr = 0; \
63 trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Apply(); \
64 } while (false)
65
66 template <typename Type>
67 struct DefaultSingletonTraits;
68
69 namespace base {
70 namespace debug {
71
72 // Time source for computing delay durations. Used for testing.
73 class TraceEventSyntheticDelayClock {
74 public:
75 TraceEventSyntheticDelayClock();
76 virtual ~TraceEventSyntheticDelayClock();
77 virtual base::TimeTicks Now() = 0;
78
79 private:
80 DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayClock);
81 };
82
83 // Single delay point instance.
84 class TraceEventSyntheticDelay {
85 public:
86 enum Mode {
87 STATIC, // Apply the configured delay every time.
88 ONE_SHOT, // Apply the configured delay just once.
89 ALTERNATING // Apply the configured delay every other time.
90 };
91
92 // Returns an existing named delay instance or creates a new one with |name|.
93 static TraceEventSyntheticDelay* Lookup(const std::string& name);
94
95 void SetTargetDuration(TimeDelta target_duration);
96 void SetMode(Mode mode);
97 void SetClock(TraceEventSyntheticDelayClock* clock);
98
99 // Establish the timing start point for the delay. No-op if the start point
100 // was already set.
101 void Activate();
102
103 // Execute the delay based on the current time and how long ago the start
104 // point was established. If Activate wasn't called, this call will be a
105 // no-op.
106 void Apply();
107
108 private:
109 TraceEventSyntheticDelay();
110 friend class TraceEventSyntheticDelayRegistry;
111
112 void Initialize(const std::string& name,
113 TraceEventSyntheticDelayClock* clock);
114 void ApplyDelay(base::TimeTicks end_time);
115
116 struct ThreadState {
117 ThreadState();
118
119 base::TimeTicks start_time;
120 unsigned trigger_count;
121 int generation;
122 };
123
124 ThreadState* EnsureThreadState();
125
126 Lock lock_;
127 Mode mode_;
128 std::string name_;
129 int generation_;
130 base::TimeDelta target_duration_;
131 ThreadLocalPointer<ThreadState> thread_state_;
132 TraceEventSyntheticDelayClock* clock_;
133
134 DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelay);
135 };
136
137 } // namespace debug
138 } // namespace base
139
140 namespace trace_event_internal {
141
142 // Helper class for scoped delays. Do not use directly.
143 class ScopedSyntheticDelay {
144 public:
145 explicit ScopedSyntheticDelay(const char* name,
146 base::subtle::AtomicWord* impl_ptr);
147 ~ScopedSyntheticDelay();
148
149 private:
150 base::debug::TraceEventSyntheticDelay* delay_impl_;
151
152 DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay);
153 };
154
155 // Helper for registering delays. Do not use directly.
156 base::debug::TraceEventSyntheticDelay* GetOrCreateDelay(
157 const char* name,
158 base::subtle::AtomicWord* impl_ptr);
159
160 } // namespace trace_event_internal
161
162 #endif /* BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ */
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698