OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014 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"); |
| 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/synchronization/lock.h" |
| 39 #include "base/time/time.h" |
| 40 |
| 41 // Apply a named delay in the current scope. |
| 42 #define TRACE_EVENT_SYNTHETIC_DELAY(name) \ |
| 43 static base::subtle::AtomicWord INTERNAL_TRACE_EVENT_UID(impl_ptr) = 0; \ |
| 44 trace_event_internal::ScopedSyntheticDelay INTERNAL_TRACE_EVENT_UID(delay)( \ |
| 45 name, &INTERNAL_TRACE_EVENT_UID(impl_ptr)); |
| 46 |
| 47 // Activate a named delay, establishing its timing start point. May be called |
| 48 // multiple times, but only the first call will have an effect. |
| 49 #define TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE(name) \ |
| 50 do { \ |
| 51 static base::subtle::AtomicWord impl_ptr = 0; \ |
| 52 trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Activate(); \ |
| 53 } while (false) |
| 54 |
| 55 // Apply a named delay. If TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE was called for |
| 56 // the same delay, that point in time is used as the delay start point. If not, |
| 57 // this call will be a no-op. |
| 58 #define TRACE_EVENT_SYNTHETIC_DELAY_APPLY(name) \ |
| 59 do { \ |
| 60 static base::subtle::AtomicWord impl_ptr = 0; \ |
| 61 trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Apply(); \ |
| 62 } while (false) |
| 63 |
| 64 template <typename Type> |
| 65 struct DefaultSingletonTraits; |
| 66 |
| 67 namespace base { |
| 68 namespace debug { |
| 69 |
| 70 // Time source for computing delay durations. Used for testing. |
| 71 class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelayClock { |
| 72 public: |
| 73 TraceEventSyntheticDelayClock(); |
| 74 virtual ~TraceEventSyntheticDelayClock(); |
| 75 virtual base::TimeTicks Now() = 0; |
| 76 |
| 77 private: |
| 78 DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayClock); |
| 79 }; |
| 80 |
| 81 // Single delay point instance. |
| 82 class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelay { |
| 83 public: |
| 84 enum Mode { |
| 85 STATIC, // Apply the configured delay every time. |
| 86 ONE_SHOT, // Apply the configured delay just once. |
| 87 ALTERNATING // Apply the configured delay every other time. |
| 88 }; |
| 89 |
| 90 // Returns an existing named delay instance or creates a new one with |name|. |
| 91 static TraceEventSyntheticDelay* Lookup(const std::string& name); |
| 92 |
| 93 void SetTargetDuration(TimeDelta target_duration); |
| 94 void SetMode(Mode mode); |
| 95 void SetClock(TraceEventSyntheticDelayClock* clock); |
| 96 |
| 97 // Establish the timing start point for the delay. No-op if the start point |
| 98 // was already set. |
| 99 void Activate(); |
| 100 |
| 101 // Execute the delay based on the current time and how long ago the start |
| 102 // point was established. If Activate wasn't called, this call will be a |
| 103 // no-op. |
| 104 void Apply(); |
| 105 |
| 106 private: |
| 107 TraceEventSyntheticDelay(); |
| 108 ~TraceEventSyntheticDelay(); |
| 109 friend class TraceEventSyntheticDelayRegistry; |
| 110 |
| 111 void Initialize(const std::string& name, |
| 112 TraceEventSyntheticDelayClock* clock, |
| 113 int thread_state_index); |
| 114 void ApplyDelay(base::TimeTicks end_time); |
| 115 |
| 116 Lock lock_; |
| 117 Mode mode_; |
| 118 std::string name_; |
| 119 int generation_; |
| 120 base::TimeDelta target_duration_; |
| 121 int thread_state_index_; |
| 122 TraceEventSyntheticDelayClock* clock_; |
| 123 |
| 124 DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelay); |
| 125 }; |
| 126 |
| 127 } // namespace debug |
| 128 } // namespace base |
| 129 |
| 130 namespace trace_event_internal { |
| 131 |
| 132 // Helper class for scoped delays. Do not use directly. |
| 133 class TRACE_EVENT_API_CLASS_EXPORT ScopedSyntheticDelay { |
| 134 public: |
| 135 explicit ScopedSyntheticDelay(const char* name, |
| 136 base::subtle::AtomicWord* impl_ptr); |
| 137 ~ScopedSyntheticDelay(); |
| 138 |
| 139 private: |
| 140 base::debug::TraceEventSyntheticDelay* delay_impl_; |
| 141 |
| 142 DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay); |
| 143 }; |
| 144 |
| 145 // Helper for registering delays. Do not use directly. |
| 146 TRACE_EVENT_API_CLASS_EXPORT base::debug::TraceEventSyntheticDelay* |
| 147 GetOrCreateDelay(const char* name, base::subtle::AtomicWord* impl_ptr); |
| 148 |
| 149 } // namespace trace_event_internal |
| 150 |
| 151 #endif /* BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ */ |
OLD | NEW |