diff options
author | acleung@chromium.org <acleung@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-27 22:11:03 +0000 |
---|---|---|
committer | acleung@chromium.org <acleung@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-27 22:11:03 +0000 |
commit | e7c417361167671013f44002044d718a1e943dc4 (patch) | |
tree | fe7e9cf7620992c6f0a4dec4254391850a55c0aa /base/debug | |
parent | d136c0e59814a01f058789001a33efba689b6158 (diff) | |
download | chromium_src-e7c417361167671013f44002044d718a1e943dc4.zip chromium_src-e7c417361167671013f44002044d718a1e943dc4.tar.gz chromium_src-e7c417361167671013f44002044d718a1e943dc4.tar.bz2 |
Revert of https://codereview.chromium.org/53923005/
Reason for revert: Breaks an official release bot
TBR=brianderson@chromium.org,nduca@chromium.org,dominikg@chromium.org,jar@chromium.org,skyostil@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=324057
Review URL: https://codereview.chromium.org/92623003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@237630 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug')
-rw-r--r-- | base/debug/trace_event_synthetic_delay.cc | 217 | ||||
-rw-r--r-- | base/debug/trace_event_synthetic_delay.h | 162 | ||||
-rw-r--r-- | base/debug/trace_event_synthetic_delay_unittest.cc | 118 |
3 files changed, 0 insertions, 497 deletions
diff --git a/base/debug/trace_event_synthetic_delay.cc b/base/debug/trace_event_synthetic_delay.cc deleted file mode 100644 index 505fe5d..0000000 --- a/base/debug/trace_event_synthetic_delay.cc +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/debug/trace_event_synthetic_delay.h" -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" -#include "base/threading/platform_thread.h" - -namespace { -const int kMaxSyntheticDelays = 32; -} // namespace - -namespace base { -namespace debug { - -TraceEventSyntheticDelayClock::TraceEventSyntheticDelayClock() {} -TraceEventSyntheticDelayClock::~TraceEventSyntheticDelayClock() {} - -class TraceEventSyntheticDelayRegistry : public TraceEventSyntheticDelayClock { - public: - static TraceEventSyntheticDelayRegistry* GetInstance(); - - TraceEventSyntheticDelay* GetOrCreateDelay(const char* name); - - // TraceEventSyntheticDelayClock implementation. - virtual base::TimeTicks Now() OVERRIDE; - - private: - TraceEventSyntheticDelayRegistry(); - - friend struct DefaultSingletonTraits<TraceEventSyntheticDelayRegistry>; - - Lock lock_; - TraceEventSyntheticDelay delays_[kMaxSyntheticDelays]; - TraceEventSyntheticDelay dummy_delay_; - base::subtle::Atomic32 delay_count_; - - DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayRegistry); -}; - -TraceEventSyntheticDelay::TraceEventSyntheticDelay() - : mode_(STATIC), generation_(0), clock_(NULL) {} - -TraceEventSyntheticDelay::~TraceEventSyntheticDelay() {} - -TraceEventSyntheticDelay* TraceEventSyntheticDelay::Lookup( - const std::string& name) { - return TraceEventSyntheticDelayRegistry::GetInstance()->GetOrCreateDelay( - name.c_str()); -} - -void TraceEventSyntheticDelay::Initialize( - const std::string& name, - TraceEventSyntheticDelayClock* clock) { - DCHECK(!thread_state_.Get()); - name_ = name; - clock_ = clock; -} - -void TraceEventSyntheticDelay::SetTargetDuration( - base::TimeDelta target_duration) { - AutoLock lock(lock_); - target_duration_ = target_duration; - generation_++; -} - -void TraceEventSyntheticDelay::SetMode(Mode mode) { - AutoLock lock(lock_); - mode_ = mode; - generation_++; -} - -void TraceEventSyntheticDelay::SetClock(TraceEventSyntheticDelayClock* clock) { - AutoLock lock(lock_); - clock_ = clock; - generation_++; -} - -TraceEventSyntheticDelay::ThreadState::ThreadState() - : trigger_count(0u), generation(0) {} - -void TraceEventSyntheticDelay::Activate() { - // 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 - // downside of this is that we may fail to apply some delays when the target - // duration changes. - ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration"); - if (!target_duration_.ToInternalValue()) - return; - - // Store the start time in a thread local struct so the same delay can be - // applied to multiple threads simultaneously. Note that the structs are - // leaked at program exit. - ThreadState* thread_state = EnsureThreadState(); - if (!thread_state->start_time.ToInternalValue()) - thread_state->start_time = clock_->Now(); -} - -TraceEventSyntheticDelay::ThreadState* -TraceEventSyntheticDelay::EnsureThreadState() { - ThreadState* thread_state = thread_state_.Get(); - if (!thread_state) - thread_state_.Set((thread_state = new ThreadState())); - return thread_state; -} - -void TraceEventSyntheticDelay::Apply() { - ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration"); - if (!target_duration_.ToInternalValue()) - return; - - ThreadState* thread_state = EnsureThreadState(); - if (!thread_state->start_time.ToInternalValue()) - return; - base::TimeTicks now = clock_->Now(); - base::TimeTicks start_time = thread_state->start_time; - base::TimeTicks end_time; - thread_state->start_time = base::TimeTicks(); - - { - AutoLock lock(lock_); - if (thread_state->generation != generation_) { - thread_state->trigger_count = 0; - thread_state->generation = generation_; - } - - if (mode_ == ONE_SHOT && thread_state->trigger_count++) - return; - else if (mode_ == ALTERNATING && thread_state->trigger_count++ % 2) - return; - - end_time = start_time + target_duration_; - if (now >= end_time) - return; - } - ApplyDelay(end_time); -} - -void TraceEventSyntheticDelay::ApplyDelay(base::TimeTicks end_time) { - TRACE_EVENT0("synthetic_delay", name_.c_str()); - while (clock_->Now() < end_time) { - // Busy loop. - } -} - -TraceEventSyntheticDelayRegistry* -TraceEventSyntheticDelayRegistry::GetInstance() { - return Singleton< - TraceEventSyntheticDelayRegistry, - LeakySingletonTraits<TraceEventSyntheticDelayRegistry> >::get(); -} - -TraceEventSyntheticDelayRegistry::TraceEventSyntheticDelayRegistry() - : delay_count_(0) {} - -TraceEventSyntheticDelay* TraceEventSyntheticDelayRegistry::GetOrCreateDelay( - const char* name) { - // Try to find an existing delay first without locking to make the common case - // fast. - int delay_count = base::subtle::Acquire_Load(&delay_count_); - for (int i = 0; i < delay_count; ++i) { - if (!strcmp(name, delays_[i].name_.c_str())) - return &delays_[i]; - } - - AutoLock lock(lock_); - delay_count = base::subtle::Acquire_Load(&delay_count_); - for (int i = 0; i < delay_count; ++i) { - if (!strcmp(name, delays_[i].name_.c_str())) - return &delays_[i]; - } - - DCHECK(delay_count < kMaxSyntheticDelays) - << "must increase kMaxSyntheticDelays"; - if (delay_count >= kMaxSyntheticDelays) - return &dummy_delay_; - - delays_[delay_count].Initialize(std::string(name), this); - base::subtle::Release_Store(&delay_count_, delay_count + 1); - return &delays_[delay_count]; -} - -base::TimeTicks TraceEventSyntheticDelayRegistry::Now() { - return base::TimeTicks::HighResNow(); -} - -} // namespace debug -} // namespace base - -namespace trace_event_internal { - -ScopedSyntheticDelay::ScopedSyntheticDelay(const char* name, - base::subtle::AtomicWord* impl_ptr) - : delay_impl_(GetOrCreateDelay(name, impl_ptr)) { - delay_impl_->Activate(); -} - -ScopedSyntheticDelay::~ScopedSyntheticDelay() { delay_impl_->Apply(); } - -base::debug::TraceEventSyntheticDelay* GetOrCreateDelay( - const char* name, - base::subtle::AtomicWord* impl_ptr) { - base::debug::TraceEventSyntheticDelay* delay_impl = - reinterpret_cast<base::debug::TraceEventSyntheticDelay*>( - base::subtle::NoBarrier_Load(impl_ptr)); - if (!delay_impl) { - delay_impl = base::debug::TraceEventSyntheticDelayRegistry::GetInstance() - ->GetOrCreateDelay(name); - base::subtle::NoBarrier_Store( - impl_ptr, reinterpret_cast<base::subtle::AtomicWord>(delay_impl)); - } - return delay_impl; -} - -} // namespace trace_event_internal diff --git a/base/debug/trace_event_synthetic_delay.h b/base/debug/trace_event_synthetic_delay.h deleted file mode 100644 index 2d10fd7..0000000 --- a/base/debug/trace_event_synthetic_delay.h +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The synthetic delay framework makes it possible to dynamically inject -// arbitrary delays into into different parts of the codebase. This can be used, -// for instance, for testing various task scheduling algorithms. -// -// The delays are specified in terms of a target duration for a given block of -// code. If the code executes faster than the duration, the thread is made to -// sleep until the deadline is met. -// -// Code can be instrumented for delays with two sets of macros. First, for -// delays that should apply within a scope, use the following macro: -// -// TRACE_EVENT_SYNTHETIC_DELAY("cc.LayerTreeHost.DrawAndSwap"); -// -// For delaying operations that span multiple scopes, use: -// -// TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE("cc.Scheduler.BeginMainFrame"); -// ... -// TRACE_EVENT_SYNTHETIC_DELAY_APPLY("cc.Scheduler.BeginMainFrame"); -// -// Here ACTIVATE establishes the start time for the delay and APPLY executes the -// delay based on the remaining time. ACTIVATE may be called one or multiple -// times before APPLY. Only the first call will have an effect. If ACTIVATE -// hasn't been called since the last call to APPLY, APPLY will be a no-op. -// -// Note that while the same delay can be applied in several threads -// simultaneously, a single delay operation cannot begin on one thread and end -// on another. - -#ifndef BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ -#define BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ - -#include "base/atomicops.h" -#include "base/debug/trace_event.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_local.h" -#include "base/time/time.h" - -// Apply a named delay in the current scope. -#define TRACE_EVENT_SYNTHETIC_DELAY(name) \ - static base::subtle::AtomicWord INTERNAL_TRACE_EVENT_UID(impl_ptr) = 0; \ - trace_event_internal::ScopedSyntheticDelay INTERNAL_TRACE_EVENT_UID(delay)( \ - name, &INTERNAL_TRACE_EVENT_UID(impl_ptr)); - -// Activate a named delay, establishing its timing start point. May be called -// multiple times, but only the first call will have an effect. -#define TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE(name) \ - do { \ - static base::subtle::AtomicWord impl_ptr = 0; \ - trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Activate(); \ - } while (false) - -// Apply a named delay. If TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE was called for -// the same delay, that point in time is used as the delay start point. If not, -// this call will be a no-op. -#define TRACE_EVENT_SYNTHETIC_DELAY_APPLY(name) \ - do { \ - static base::subtle::AtomicWord impl_ptr = 0; \ - trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Apply(); \ - } while (false) - -template <typename Type> -struct DefaultSingletonTraits; - -namespace base { -namespace debug { - -// Time source for computing delay durations. Used for testing. -class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelayClock { - public: - TraceEventSyntheticDelayClock(); - virtual ~TraceEventSyntheticDelayClock(); - virtual base::TimeTicks Now() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayClock); -}; - -// Single delay point instance. -class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelay { - public: - enum Mode { - STATIC, // Apply the configured delay every time. - ONE_SHOT, // Apply the configured delay just once. - ALTERNATING // Apply the configured delay every other time. - }; - - // Returns an existing named delay instance or creates a new one with |name|. - static TraceEventSyntheticDelay* Lookup(const std::string& name); - - void SetTargetDuration(TimeDelta target_duration); - void SetMode(Mode mode); - void SetClock(TraceEventSyntheticDelayClock* clock); - - // Establish the timing start point for the delay. No-op if the start point - // was already set. - void Activate(); - - // Execute the delay based on the current time and how long ago the start - // point was established. If Activate wasn't called, this call will be a - // no-op. - void Apply(); - - private: - TraceEventSyntheticDelay(); - ~TraceEventSyntheticDelay(); - friend class TraceEventSyntheticDelayRegistry; - - void Initialize(const std::string& name, - TraceEventSyntheticDelayClock* clock); - void ApplyDelay(base::TimeTicks end_time); - - struct ThreadState { - ThreadState(); - - base::TimeTicks start_time; - unsigned trigger_count; - int generation; - }; - - ThreadState* EnsureThreadState(); - - Lock lock_; - Mode mode_; - std::string name_; - int generation_; - base::TimeDelta target_duration_; - ThreadLocalPointer<ThreadState> thread_state_; - TraceEventSyntheticDelayClock* clock_; - - DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelay); -}; - -} // namespace debug -} // namespace base - -namespace trace_event_internal { - -// Helper class for scoped delays. Do not use directly. -class TRACE_EVENT_API_CLASS_EXPORT ScopedSyntheticDelay { - public: - explicit ScopedSyntheticDelay(const char* name, - base::subtle::AtomicWord* impl_ptr); - ~ScopedSyntheticDelay(); - - private: - base::debug::TraceEventSyntheticDelay* delay_impl_; - - DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay); -}; - -// Helper for registering delays. Do not use directly. -TRACE_EVENT_API_CLASS_EXPORT base::debug::TraceEventSyntheticDelay* - GetOrCreateDelay(const char* name, base::subtle::AtomicWord* impl_ptr); - -} // namespace trace_event_internal - -#endif /* BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ */ diff --git a/base/debug/trace_event_synthetic_delay_unittest.cc b/base/debug/trace_event_synthetic_delay_unittest.cc deleted file mode 100644 index 6e7e508..0000000 --- a/base/debug/trace_event_synthetic_delay_unittest.cc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/debug/trace_event_synthetic_delay.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace debug { -namespace { - -const int kTargetDurationMs = 100; -// Allow some leeway in timings to make it possible to run these tests with a -// wall clock time source too. -const int kShortDurationMs = 10; - -} // namespace - -class TraceEventSyntheticDelayTest : public testing::Test, - public TraceEventSyntheticDelayClock { - public: - TraceEventSyntheticDelayTest() {} - - // TraceEventSyntheticDelayClock implementation. - virtual base::TimeTicks Now() OVERRIDE { - AdvanceTime(base::TimeDelta::FromMilliseconds(kShortDurationMs / 10)); - return now_; - } - - TraceEventSyntheticDelay* ConfigureDelay(const char* name) { - TraceEventSyntheticDelay* delay = TraceEventSyntheticDelay::Lookup(name); - delay->SetClock(this); - delay->SetTargetDuration( - base::TimeDelta::FromMilliseconds(kTargetDurationMs)); - return delay; - } - - void AdvanceTime(base::TimeDelta delta) { now_ += delta; } - - int TestFunction() { - base::TimeTicks start = Now(); - { TRACE_EVENT_SYNTHETIC_DELAY("test.Delay"); } - return (Now() - start).InMilliseconds(); - } - - int AsyncTestFunctionActivate() { - base::TimeTicks start = Now(); - { TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE("test.AsyncDelay"); } - return (Now() - start).InMilliseconds(); - } - - int AsyncTestFunctionApply() { - base::TimeTicks start = Now(); - { TRACE_EVENT_SYNTHETIC_DELAY_APPLY("test.AsyncDelay"); } - return (Now() - start).InMilliseconds(); - } - - private: - base::TimeTicks now_; - - DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayTest); -}; - -TEST_F(TraceEventSyntheticDelayTest, StaticDelay) { - TraceEventSyntheticDelay* delay = ConfigureDelay("test.Delay"); - delay->SetMode(TraceEventSyntheticDelay::STATIC); - EXPECT_GE(TestFunction(), kTargetDurationMs); -} - -TEST_F(TraceEventSyntheticDelayTest, OneShotDelay) { - TraceEventSyntheticDelay* delay = ConfigureDelay("test.Delay"); - delay->SetMode(TraceEventSyntheticDelay::ONE_SHOT); - EXPECT_GE(TestFunction(), kTargetDurationMs); - EXPECT_LT(TestFunction(), kShortDurationMs); - - delay->SetTargetDuration( - base::TimeDelta::FromMilliseconds(kTargetDurationMs)); - EXPECT_GE(TestFunction(), kTargetDurationMs); -} - -TEST_F(TraceEventSyntheticDelayTest, AlternatingDelay) { - TraceEventSyntheticDelay* delay = ConfigureDelay("test.Delay"); - delay->SetMode(TraceEventSyntheticDelay::ALTERNATING); - EXPECT_GE(TestFunction(), kTargetDurationMs); - EXPECT_LT(TestFunction(), kShortDurationMs); - EXPECT_GE(TestFunction(), kTargetDurationMs); - EXPECT_LT(TestFunction(), kShortDurationMs); -} - -TEST_F(TraceEventSyntheticDelayTest, AsyncDelay) { - ConfigureDelay("test.AsyncDelay"); - EXPECT_LT(AsyncTestFunctionActivate(), kShortDurationMs); - EXPECT_GE(AsyncTestFunctionApply(), kTargetDurationMs / 2); -} - -TEST_F(TraceEventSyntheticDelayTest, AsyncDelayExceeded) { - ConfigureDelay("test.AsyncDelay"); - EXPECT_LT(AsyncTestFunctionActivate(), kShortDurationMs); - AdvanceTime(base::TimeDelta::FromMilliseconds(kTargetDurationMs)); - EXPECT_LT(AsyncTestFunctionApply(), kShortDurationMs); -} - -TEST_F(TraceEventSyntheticDelayTest, AsyncDelayNoActivation) { - ConfigureDelay("test.AsyncDelay"); - EXPECT_LT(AsyncTestFunctionApply(), kShortDurationMs); -} - -TEST_F(TraceEventSyntheticDelayTest, AsyncDelayMultipleActivations) { - ConfigureDelay("test.AsyncDelay"); - EXPECT_LT(AsyncTestFunctionActivate(), kShortDurationMs); - AdvanceTime(base::TimeDelta::FromMilliseconds(kTargetDurationMs)); - EXPECT_LT(AsyncTestFunctionActivate(), kShortDurationMs); - EXPECT_LT(AsyncTestFunctionApply(), kShortDurationMs); -} - -} // namespace debug -} // namespace base |