15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The synthetic delay framework makes it possible to dynamically inject 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// arbitrary delays into into different parts of the codebase. This can be used, 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// for instance, for testing various task scheduling algorithms. 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The delays are specified in terms of a target duration for a given block of 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// code. If the code executes faster than the duration, the thread is made to 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// sleep until the deadline is met. 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Code can be instrumented for delays with two sets of macros. First, for 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// delays that should apply within a scope, use the following macro: 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TRACE_EVENT_SYNTHETIC_DELAY("cc.LayerTreeHost.DrawAndSwap"); 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// For delaying operations that span multiple scopes, use: 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.Scheduler.BeginMainFrame"); 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ... 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TRACE_EVENT_SYNTHETIC_DELAY_END("cc.Scheduler.BeginMainFrame"); 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Here BEGIN establishes the start time for the delay and END executes the 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// delay based on the remaining time. If BEGIN is called multiple times in a 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// row, END should be called a corresponding number of times. Only the last 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// call to END will have an effect. 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Note that a single delay may begin on one thread and end on another. This 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// implies that a single delay cannot not be applied in several threads at once. 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/atomicops.h" 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/debug/trace_event.h" 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/synchronization/lock.h" 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/time.h" 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Apply a named delay in the current scope. 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define TRACE_EVENT_SYNTHETIC_DELAY(name) \ 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static base::subtle::AtomicWord INTERNAL_TRACE_EVENT_UID(impl_ptr) = 0; \ 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_event_internal::ScopedSyntheticDelay INTERNAL_TRACE_EVENT_UID(delay)( \ 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) name, &INTERNAL_TRACE_EVENT_UID(impl_ptr)); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Begin a named delay, establishing its timing start point. May be called 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// multiple times as long as the calls to TRACE_EVENT_SYNTHETIC_DELAY_END are 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// balanced. Only the first call records the timing start point. 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define TRACE_EVENT_SYNTHETIC_DELAY_BEGIN(name) \ 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) do { \ 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static base::subtle::AtomicWord impl_ptr = 0; \ 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Begin(); \ 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } while (false) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// End a named delay. The delay is applied only if this call matches the 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// first corresponding call to TRACE_EVENT_SYNTHETIC_DELAY_BEGIN with the 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// same delay. 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define TRACE_EVENT_SYNTHETIC_DELAY_END(name) \ 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) do { \ 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static base::subtle::AtomicWord impl_ptr = 0; \ 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->End(); \ 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } while (false) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Type> 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct DefaultSingletonTraits; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace base { 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace debug { 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Time source for computing delay durations. Used for testing. 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelayClock { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TraceEventSyntheticDelayClock(); 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~TraceEventSyntheticDelayClock(); 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual base::TimeTicks Now() = 0; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayClock); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Single delay point instance. 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelay { 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum Mode { 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) STATIC, // Apply the configured delay every time. 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ONE_SHOT, // Apply the configured delay just once. 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ALTERNATING // Apply the configured delay every other time. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Returns an existing named delay instance or creates a new one with |name|. 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static TraceEventSyntheticDelay* Lookup(const std::string& name); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetTargetDuration(TimeDelta target_duration); 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetMode(Mode mode); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetClock(TraceEventSyntheticDelayClock* clock); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Begin the delay, establishing its timing start point. May be called 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // multiple times as long as the calls to End() are balanced. Only the first 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // call records the timing start point. 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Begin(); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // End the delay. The delay is applied only if this call matches the first 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // corresponding call to Begin() with the same delay. 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void End(); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Begin a parallel instance of the delay. Several parallel instances may be 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // active simultaneously and will complete independently. The computed end 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // time for the delay is stored in |out_end_time|, which should later be 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // passed to EndParallel(). 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void BeginParallel(base::TimeTicks* out_end_time); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // End a previously started parallel delay. |end_time| is the delay end point 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // computed by BeginParallel(). 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void EndParallel(base::TimeTicks end_time); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TraceEventSyntheticDelay(); 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~TraceEventSyntheticDelay(); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) friend class TraceEventSyntheticDelayRegistry; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Initialize(const std::string& name, 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TraceEventSyntheticDelayClock* clock); 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks CalculateEndTimeLocked(base::TimeTicks start_time); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void ApplyDelay(base::TimeTicks end_time); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Lock lock_; 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Mode mode_; 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string name_; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int begin_count_; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int trigger_count_; 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks end_time_; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta target_duration_; 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TraceEventSyntheticDelayClock* clock_; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelay); 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Set the target durations of all registered synthetic delay points to zero. 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TRACE_EVENT_API_CLASS_EXPORT void ResetTraceEventSyntheticDelays(); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace debug 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace base 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace trace_event_internal { 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Helper class for scoped delays. Do not use directly. 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TRACE_EVENT_API_CLASS_EXPORT ScopedSyntheticDelay { 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit ScopedSyntheticDelay(const char* name, 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::subtle::AtomicWord* impl_ptr); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~ScopedSyntheticDelay(); 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::debug::TraceEventSyntheticDelay* delay_impl_; 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks end_time_; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay); 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Helper for registering delays. Do not use directly. 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TRACE_EVENT_API_CLASS_EXPORT base::debug::TraceEventSyntheticDelay* 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetOrCreateDelay(const char* name, base::subtle::AtomicWord* impl_ptr); 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace trace_event_internal 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif /* BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ */ 167