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

Unified Diff: base/debug/trace_event_synthetic_delay.cc

Issue 104613003: Use Begin/End semantics for synthetic delays (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Created 6 years, 11 months 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/debug/trace_event_synthetic_delay.cc
diff --git a/base/debug/trace_event_synthetic_delay.cc b/base/debug/trace_event_synthetic_delay.cc
index 939d9602653ed55e59cba6de2f85fa38e830d6c2..0d07a70c6a5fc3e3fd5414bd378462ad2674a286 100644
--- a/base/debug/trace_event_synthetic_delay.cc
+++ b/base/debug/trace_event_synthetic_delay.cc
@@ -4,8 +4,6 @@
#include "base/debug/trace_event_synthetic_delay.h"
#include "base/memory/singleton.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local.h"
namespace {
const int kMaxSyntheticDelays = 32;
@@ -17,24 +15,12 @@ namespace debug {
TraceEventSyntheticDelayClock::TraceEventSyntheticDelayClock() {}
TraceEventSyntheticDelayClock::~TraceEventSyntheticDelayClock() {}
-// Thread-local state for each synthetic delay point. This allows the same delay
-// to be applied to multiple threads simultaneously.
-struct ThreadState {
- ThreadState();
-
- base::TimeTicks start_time;
- unsigned trigger_count;
- int generation;
-};
-
-ThreadState::ThreadState() : trigger_count(0u), generation(0) {}
-
class TraceEventSyntheticDelayRegistry : public TraceEventSyntheticDelayClock {
public:
static TraceEventSyntheticDelayRegistry* GetInstance();
TraceEventSyntheticDelay* GetOrCreateDelay(const char* name);
- ThreadState* GetThreadState(int index);
+ void ResetAllDelays();
// TraceEventSyntheticDelayClock implementation.
virtual base::TimeTicks Now() OVERRIDE;
@@ -49,13 +35,11 @@ class TraceEventSyntheticDelayRegistry : public TraceEventSyntheticDelayClock {
TraceEventSyntheticDelay dummy_delay_;
base::subtle::Atomic32 delay_count_;
- ThreadLocalPointer<ThreadState> thread_states_;
-
DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayRegistry);
};
TraceEventSyntheticDelay::TraceEventSyntheticDelay()
- : mode_(STATIC), generation_(0), thread_state_index_(0), clock_(NULL) {}
+ : mode_(STATIC), begin_count_(0), trigger_count_(0), clock_(NULL) {}
TraceEventSyntheticDelay::~TraceEventSyntheticDelay() {}
@@ -67,33 +51,30 @@ TraceEventSyntheticDelay* TraceEventSyntheticDelay::Lookup(
void TraceEventSyntheticDelay::Initialize(
const std::string& name,
- TraceEventSyntheticDelayClock* clock,
- int thread_state_index) {
+ TraceEventSyntheticDelayClock* clock) {
name_ = name;
clock_ = clock;
- thread_state_index_ = thread_state_index;
}
void TraceEventSyntheticDelay::SetTargetDuration(
base::TimeDelta target_duration) {
AutoLock lock(lock_);
target_duration_ = target_duration;
- generation_++;
+ trigger_count_ = 0;
+ begin_count_ = 0;
}
void TraceEventSyntheticDelay::SetMode(Mode mode) {
AutoLock lock(lock_);
mode_ = mode;
- generation_++;
}
void TraceEventSyntheticDelay::SetClock(TraceEventSyntheticDelayClock* clock) {
AutoLock lock(lock_);
clock_ = clock;
- generation_++;
}
-void TraceEventSyntheticDelay::Activate() {
+void TraceEventSyntheticDelay::Begin() {
// Note that we check for a non-zero target duration without locking to keep
// things quick for the common case when delays are disabled. Since the delay
// calculation is done with a lock held, it will always be correct. The only
@@ -103,45 +84,59 @@ void TraceEventSyntheticDelay::Activate() {
if (!target_duration_.ToInternalValue())
return;
- ThreadState* thread_state =
- TraceEventSyntheticDelayRegistry::GetInstance()->
- GetThreadState(thread_state_index_);
- if (!thread_state->start_time.ToInternalValue())
- thread_state->start_time = clock_->Now();
+ base::TimeTicks start_time = clock_->Now();
+ {
+ AutoLock lock(lock_);
+ if (++begin_count_ != 1)
+ return;
+ end_time_ = CalculateEndTimeLocked(start_time);
+ }
}
-void TraceEventSyntheticDelay::Apply() {
+void TraceEventSyntheticDelay::BeginParallel(base::TimeTicks* out_end_time) {
+ // See note in Begin().
ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration");
- if (!target_duration_.ToInternalValue())
- return;
-
- ThreadState* thread_state =
- TraceEventSyntheticDelayRegistry::GetInstance()->
- GetThreadState(thread_state_index_);
- if (!thread_state->start_time.ToInternalValue())
+ if (!target_duration_.ToInternalValue()) {
+ *out_end_time = base::TimeTicks();
return;
- base::TimeTicks now = clock_->Now();
- base::TimeTicks start_time = thread_state->start_time;
- base::TimeTicks end_time;
- thread_state->start_time = base::TimeTicks();
+ }
+ base::TimeTicks start_time = clock_->Now();
{
AutoLock lock(lock_);
- if (thread_state->generation != generation_) {
- thread_state->trigger_count = 0;
- thread_state->generation = generation_;
- }
+ *out_end_time = CalculateEndTimeLocked(start_time);
+ }
+}
- if (mode_ == ONE_SHOT && thread_state->trigger_count++)
- return;
- else if (mode_ == ALTERNATING && thread_state->trigger_count++ % 2)
- return;
+void TraceEventSyntheticDelay::End() {
+ // See note in Begin().
+ ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration");
+ if (!target_duration_.ToInternalValue())
+ return;
- end_time = start_time + target_duration_;
- if (now >= end_time)
+ base::TimeTicks end_time;
+ {
+ AutoLock lock(lock_);
+ if (!begin_count_ || --begin_count_ != 0)
return;
+ end_time = end_time_;
}
- ApplyDelay(end_time);
+ if (!end_time.is_null())
+ ApplyDelay(end_time);
+}
+
+void TraceEventSyntheticDelay::EndParallel(base::TimeTicks end_time) {
+ if (!end_time.is_null())
+ ApplyDelay(end_time);
+}
+
+base::TimeTicks TraceEventSyntheticDelay::CalculateEndTimeLocked(
+ base::TimeTicks start_time) {
+ if (mode_ == ONE_SHOT && trigger_count_++)
+ return base::TimeTicks();
+ else if (mode_ == ALTERNATING && trigger_count_++ % 2)
+ return base::TimeTicks();
+ return start_time + target_duration_;
}
void TraceEventSyntheticDelay::ApplyDelay(base::TimeTicks end_time) {
@@ -183,26 +178,24 @@ TraceEventSyntheticDelay* TraceEventSyntheticDelayRegistry::GetOrCreateDelay(
if (delay_count >= kMaxSyntheticDelays)
return &dummy_delay_;
- delays_[delay_count].Initialize(std::string(name), this, delay_count);
+ delays_[delay_count].Initialize(std::string(name), this);
base::subtle::Release_Store(&delay_count_, delay_count + 1);
return &delays_[delay_count];
}
-ThreadState* TraceEventSyntheticDelayRegistry::GetThreadState(int index) {
- DCHECK(index >= 0 && index < kMaxSyntheticDelays);
- if (index < 0 || index >= kMaxSyntheticDelays)
- return NULL;
+base::TimeTicks TraceEventSyntheticDelayRegistry::Now() {
+ return base::TimeTicks::HighResNow();
+}
- // Note that these thread states are leaked at program exit. They will only
- // get allocated if synthetic delays are actually used.
- ThreadState* thread_states = thread_states_.Get();
- if (!thread_states)
- thread_states_.Set((thread_states = new ThreadState[kMaxSyntheticDelays]));
- return &thread_states[index];
+void TraceEventSyntheticDelayRegistry::ResetAllDelays() {
+ AutoLock lock(lock_);
+ int delay_count = base::subtle::Acquire_Load(&delay_count_);
+ for (int i = 0; i < delay_count; ++i)
+ delays_[i].SetTargetDuration(base::TimeDelta());
}
-base::TimeTicks TraceEventSyntheticDelayRegistry::Now() {
- return base::TimeTicks::HighResNow();
+void ResetTraceEventSyntheticDelays() {
+ TraceEventSyntheticDelayRegistry::GetInstance()->ResetAllDelays();
}
} // namespace debug
@@ -213,10 +206,12 @@ namespace trace_event_internal {
ScopedSyntheticDelay::ScopedSyntheticDelay(const char* name,
base::subtle::AtomicWord* impl_ptr)
: delay_impl_(GetOrCreateDelay(name, impl_ptr)) {
- delay_impl_->Activate();
+ delay_impl_->BeginParallel(&end_time_);
}
-ScopedSyntheticDelay::~ScopedSyntheticDelay() { delay_impl_->Apply(); }
+ScopedSyntheticDelay::~ScopedSyntheticDelay() {
+ delay_impl_->EndParallel(end_time_);
+}
base::debug::TraceEventSyntheticDelay* GetOrCreateDelay(
const char* name,
« 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