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

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

Issue 92623003: Revert of Add synthetic delay testing framework (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years 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 #include "base/debug/trace_event_synthetic_delay.h"
6 #include "base/memory/singleton.h"
7 #include "base/synchronization/lock.h"
8 #include "base/threading/platform_thread.h"
9
10 namespace {
11 const int kMaxSyntheticDelays = 32;
12 } // namespace
13
14 namespace base {
15 namespace debug {
16
17 TraceEventSyntheticDelayClock::TraceEventSyntheticDelayClock() {}
18 TraceEventSyntheticDelayClock::~TraceEventSyntheticDelayClock() {}
19
20 class TraceEventSyntheticDelayRegistry : public TraceEventSyntheticDelayClock {
21 public:
22 static TraceEventSyntheticDelayRegistry* GetInstance();
23
24 TraceEventSyntheticDelay* GetOrCreateDelay(const char* name);
25
26 // TraceEventSyntheticDelayClock implementation.
27 virtual base::TimeTicks Now() OVERRIDE;
28
29 private:
30 TraceEventSyntheticDelayRegistry();
31
32 friend struct DefaultSingletonTraits<TraceEventSyntheticDelayRegistry>;
33
34 Lock lock_;
35 TraceEventSyntheticDelay delays_[kMaxSyntheticDelays];
36 TraceEventSyntheticDelay dummy_delay_;
37 base::subtle::Atomic32 delay_count_;
38
39 DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayRegistry);
40 };
41
42 TraceEventSyntheticDelay::TraceEventSyntheticDelay()
43 : mode_(STATIC), generation_(0), clock_(NULL) {}
44
45 TraceEventSyntheticDelay::~TraceEventSyntheticDelay() {}
46
47 TraceEventSyntheticDelay* TraceEventSyntheticDelay::Lookup(
48 const std::string& name) {
49 return TraceEventSyntheticDelayRegistry::GetInstance()->GetOrCreateDelay(
50 name.c_str());
51 }
52
53 void TraceEventSyntheticDelay::Initialize(
54 const std::string& name,
55 TraceEventSyntheticDelayClock* clock) {
56 DCHECK(!thread_state_.Get());
57 name_ = name;
58 clock_ = clock;
59 }
60
61 void TraceEventSyntheticDelay::SetTargetDuration(
62 base::TimeDelta target_duration) {
63 AutoLock lock(lock_);
64 target_duration_ = target_duration;
65 generation_++;
66 }
67
68 void TraceEventSyntheticDelay::SetMode(Mode mode) {
69 AutoLock lock(lock_);
70 mode_ = mode;
71 generation_++;
72 }
73
74 void TraceEventSyntheticDelay::SetClock(TraceEventSyntheticDelayClock* clock) {
75 AutoLock lock(lock_);
76 clock_ = clock;
77 generation_++;
78 }
79
80 TraceEventSyntheticDelay::ThreadState::ThreadState()
81 : trigger_count(0u), generation(0) {}
82
83 void TraceEventSyntheticDelay::Activate() {
84 // Note that we check for a non-zero target duration without locking to keep
85 // things quick for the common case when delays are disabled. Since the delay
86 // calculation is done with a lock held, it will always be correct. The only
87 // downside of this is that we may fail to apply some delays when the target
88 // duration changes.
89 ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration");
90 if (!target_duration_.ToInternalValue())
91 return;
92
93 // Store the start time in a thread local struct so the same delay can be
94 // applied to multiple threads simultaneously. Note that the structs are
95 // leaked at program exit.
96 ThreadState* thread_state = EnsureThreadState();
97 if (!thread_state->start_time.ToInternalValue())
98 thread_state->start_time = clock_->Now();
99 }
100
101 TraceEventSyntheticDelay::ThreadState*
102 TraceEventSyntheticDelay::EnsureThreadState() {
103 ThreadState* thread_state = thread_state_.Get();
104 if (!thread_state)
105 thread_state_.Set((thread_state = new ThreadState()));
106 return thread_state;
107 }
108
109 void TraceEventSyntheticDelay::Apply() {
110 ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration");
111 if (!target_duration_.ToInternalValue())
112 return;
113
114 ThreadState* thread_state = EnsureThreadState();
115 if (!thread_state->start_time.ToInternalValue())
116 return;
117 base::TimeTicks now = clock_->Now();
118 base::TimeTicks start_time = thread_state->start_time;
119 base::TimeTicks end_time;
120 thread_state->start_time = base::TimeTicks();
121
122 {
123 AutoLock lock(lock_);
124 if (thread_state->generation != generation_) {
125 thread_state->trigger_count = 0;
126 thread_state->generation = generation_;
127 }
128
129 if (mode_ == ONE_SHOT && thread_state->trigger_count++)
130 return;
131 else if (mode_ == ALTERNATING && thread_state->trigger_count++ % 2)
132 return;
133
134 end_time = start_time + target_duration_;
135 if (now >= end_time)
136 return;
137 }
138 ApplyDelay(end_time);
139 }
140
141 void TraceEventSyntheticDelay::ApplyDelay(base::TimeTicks end_time) {
142 TRACE_EVENT0("synthetic_delay", name_.c_str());
143 while (clock_->Now() < end_time) {
144 // Busy loop.
145 }
146 }
147
148 TraceEventSyntheticDelayRegistry*
149 TraceEventSyntheticDelayRegistry::GetInstance() {
150 return Singleton<
151 TraceEventSyntheticDelayRegistry,
152 LeakySingletonTraits<TraceEventSyntheticDelayRegistry> >::get();
153 }
154
155 TraceEventSyntheticDelayRegistry::TraceEventSyntheticDelayRegistry()
156 : delay_count_(0) {}
157
158 TraceEventSyntheticDelay* TraceEventSyntheticDelayRegistry::GetOrCreateDelay(
159 const char* name) {
160 // Try to find an existing delay first without locking to make the common case
161 // fast.
162 int delay_count = base::subtle::Acquire_Load(&delay_count_);
163 for (int i = 0; i < delay_count; ++i) {
164 if (!strcmp(name, delays_[i].name_.c_str()))
165 return &delays_[i];
166 }
167
168 AutoLock lock(lock_);
169 delay_count = base::subtle::Acquire_Load(&delay_count_);
170 for (int i = 0; i < delay_count; ++i) {
171 if (!strcmp(name, delays_[i].name_.c_str()))
172 return &delays_[i];
173 }
174
175 DCHECK(delay_count < kMaxSyntheticDelays)
176 << "must increase kMaxSyntheticDelays";
177 if (delay_count >= kMaxSyntheticDelays)
178 return &dummy_delay_;
179
180 delays_[delay_count].Initialize(std::string(name), this);
181 base::subtle::Release_Store(&delay_count_, delay_count + 1);
182 return &delays_[delay_count];
183 }
184
185 base::TimeTicks TraceEventSyntheticDelayRegistry::Now() {
186 return base::TimeTicks::HighResNow();
187 }
188
189 } // namespace debug
190 } // namespace base
191
192 namespace trace_event_internal {
193
194 ScopedSyntheticDelay::ScopedSyntheticDelay(const char* name,
195 base::subtle::AtomicWord* impl_ptr)
196 : delay_impl_(GetOrCreateDelay(name, impl_ptr)) {
197 delay_impl_->Activate();
198 }
199
200 ScopedSyntheticDelay::~ScopedSyntheticDelay() { delay_impl_->Apply(); }
201
202 base::debug::TraceEventSyntheticDelay* GetOrCreateDelay(
203 const char* name,
204 base::subtle::AtomicWord* impl_ptr) {
205 base::debug::TraceEventSyntheticDelay* delay_impl =
206 reinterpret_cast<base::debug::TraceEventSyntheticDelay*>(
207 base::subtle::NoBarrier_Load(impl_ptr));
208 if (!delay_impl) {
209 delay_impl = base::debug::TraceEventSyntheticDelayRegistry::GetInstance()
210 ->GetOrCreateDelay(name);
211 base::subtle::NoBarrier_Store(
212 impl_ptr, reinterpret_cast<base::subtle::AtomicWord>(delay_impl));
213 }
214 return delay_impl;
215 }
216
217 } // namespace trace_event_internal
OLDNEW
« no previous file with comments | « base/debug/trace_event_synthetic_delay.h ('k') | base/debug/trace_event_synthetic_delay_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698