8#ifndef PXR_ARCH_TIMING_H
9#define PXR_ARCH_TIMING_H
14#include "pxr/arch/pxr.h"
15#include "pxr/arch/api.h"
19#if defined(ARCH_OS_LINUX) && defined(ARCH_CPU_INTEL)
21#elif defined(ARCH_OS_WASM_VM)
22#include <emscripten.h>
23#elif defined(ARCH_OS_DARWIN)
24#include <mach/mach_time.h>
25#elif defined(ARCH_OS_WINDOWS)
34ARCH_NAMESPACE_OPEN_SCOPE
46#if defined(ARCH_OS_DARWIN)
48 return mach_absolute_time();
49#elif defined(ARCH_CPU_INTEL)
52#elif defined (ARCH_CPU_ARM)
54 #if defined(ARCH_COMPILER_MSVC)
57 result = _ReadStatusReg(0x5F02);
59 __asm __volatile(
"mrs %0, CNTVCT_EL0" :
"=&r" (result));
62#elif defined(ARCH_OS_WASM_VM)
63 return static_cast<int64_t
>(emscripten_get_now() * 1e+6);
65#error Unknown architecture.
78#if defined (ARCH_OS_DARWIN) || defined(ARCH_OS_WASM_VM) || \
79 (defined (ARCH_CPU_ARM) && defined (ARCH_COMPILER_MSVC))
81#elif defined (ARCH_CPU_ARM)
82 std::atomic_signal_fence(std::memory_order_seq_cst);
83 asm volatile(
"mrs %0, cntvct_el0" :
"=r"(t));
84 std::atomic_signal_fence(std::memory_order_seq_cst);
85#elif defined (ARCH_COMPILER_MSVC)
87 std::atomic_signal_fence(std::memory_order_seq_cst);
90 std::atomic_signal_fence(std::memory_order_seq_cst);
91#elif defined(ARCH_CPU_INTEL) && \
92 (defined(ARCH_COMPILER_CLANG) || defined(ARCH_COMPILER_GCC))
94 std::atomic_signal_fence(std::memory_order_seq_cst);
107#error "Unsupported architecture."
120#if defined (ARCH_OS_DARWIN) || defined(ARCH_OS_WASM_VM) || \
121 (defined (ARCH_CPU_ARM) && defined (ARCH_COMPILER_MSVC))
123#elif defined (ARCH_CPU_ARM)
124 std::atomic_signal_fence(std::memory_order_seq_cst);
125 asm volatile(
"mrs %0, cntvct_el0" :
"=r"(t));
126 std::atomic_signal_fence(std::memory_order_seq_cst);
127#elif defined (ARCH_COMPILER_MSVC)
128 std::atomic_signal_fence(std::memory_order_seq_cst);
132 std::atomic_signal_fence(std::memory_order_seq_cst);
133#elif defined(ARCH_CPU_INTEL) && \
134 (defined(ARCH_COMPILER_CLANG) || defined(ARCH_COMPILER_GCC))
135 std::atomic_signal_fence(std::memory_order_seq_cst);
145 :
"rcx",
"rdx",
"cc");
147#error "Unsupported architecture."
152#if defined (doxygen) || \
153 (!defined(ARCH_OS_DARWIN) && defined(ARCH_CPU_INTEL) && \
154 (defined(ARCH_COMPILER_CLANG) || defined(ARCH_COMPILER_GCC)))
171 std::atomic_signal_fence(std::memory_order_seq_cst);
176 :
"=a"(_startLow),
"=d"(_startHigh) :: );
186 return (uint64_t(_startHigh) << 32) + _startLow;
200 uint32_t stopLow, stopHigh;
201 std::atomic_signal_fence(std::memory_order_seq_cst);
205 :
"=a"(stopLow),
"=d"(stopHigh)
209 return ((uint64_t(stopHigh) << 32) + stopLow) -
210 ((uint64_t(_startHigh) << 32) + _startLow);
213 bool _started =
false;
214 uint32_t _startLow = 0, _startHigh = 0;
219struct ArchIntervalTimer
221 explicit ArchIntervalTimer(
bool start=
true)
224 _startTicks = ArchGetStartTickTime();
233 bool IsStarted()
const {
237 uint64_t GetStartTicks()
const {
241 uint64_t GetCurrentTicks() {
245 uint64_t GetElapsedTicks() {
252 bool _started =
false;
253 uint64_t _startTicks;
310 void const *m, uint64_t (*callM)(
void const *,
int));
325 uint64_t maxTicks = 1e7,
326 bool *reachedConsensus =
nullptr)
328 auto measureN = [&fn](
int nTimes) -> uint64_t {
330 for (
int i = nTimes; i--; ) {
331 std::atomic_signal_fence(std::memory_order_seq_cst);
333 std::atomic_signal_fence(std::memory_order_seq_cst);
335 return iTimer.GetElapsedTicks();
338 using MeasureNType =
decltype(measureN);
341 maxTicks, reachedConsensus,
342 static_cast<void const *
>(&measureN),
343 [](
void const *mN,
int nTimes) {
344 return (*
static_cast<MeasureNType
const *
>(mN))(nTimes);
348ARCH_NAMESPACE_CLOSE_SCOPE
uint64_t ArchGetIntervalTimerTickOverhead()
Return the ticks taken to record an interval of time with ArchIntervalTimer, as measured at startup t...
uint64_t ArchGetTickQuantum()
Return the tick time resolution.
double ArchGetNanosecondsPerTick()
Get nanoseconds per tick.
uint64_t ArchGetStartTickTime()
Get a "start" tick time for measuring an interval of time, followed by a later call to ArchGetStopTic...
Definition timing.h:75
uint64_t ArchGetTickTime()
Return the current time in system-dependent units.
Definition timing.h:44
uint64_t ArchSecondsToTicks(double seconds)
Convert a duration in seconds to "ticks", as returned by ArchGetTickTime().
uint64_t ArchMeasureExecutionTime(Fn const &fn, uint64_t maxTicks=1e7, bool *reachedConsensus=nullptr)
Run fn repeatedly attempting to determine a consensus fastest execution time with low noise,...
Definition timing.h:323
uint64_t Arch_MeasureExecutionTime(uint64_t maxTicks, bool *reachedConsensus, void const *m, uint64_t(*callM)(void const *, int))
int64_t ArchTicksToNanoseconds(uint64_t nTicks)
Convert a duration measured in "ticks", as returned by ArchGetTickTime(), to nanoseconds.
double ArchTicksToSeconds(uint64_t nTicks)
Convert a duration measured in "ticks", as returned by ArchGetTickTime(), to seconds.
uint64_t ArchGetStopTickTime()
Get a "stop" tick time for measuring an interval of time.
Definition timing.h:117
A simple timer class for measuring an interval of time using the ArchTickTimer facilities.
Definition timing.h:159
uint64_t GetStartTicks() const
Return this timer's start time, or 0 if it hasn't been started.
Definition timing.h:185
void Start()
Start the timer, or reset the start time if it has already been started.
Definition timing.h:169
bool IsStarted() const
Return true if this timer is started.
Definition timing.h:180
ArchIntervalTimer(bool start=true)
Construct a timer and start timing if start is true.
Definition timing.h:161
uint64_t GetCurrentTicks()
Read and return the current time.
Definition timing.h:190
uint64_t GetElapsedTicks()
Read the current time and return the difference between it and the start time.
Definition timing.h:196