8#include <dispenso/timing.h>
23#include <mach/mach_time.h>
28#if defined(__x86_64__) || defined(_M_AMD64)
29#define DISPENSO_HAS_TIMESTAMP
31inline uint64_t rdtscp() {
37inline uint64_t rdtscp() {
39 __asm__
volatile(
"rdtscp"
43 return (uint64_t)lo | (((uint64_t)hi) << 32);
46#elif (defined(__GNUC__) || defined(__clang__)) && defined(__aarch64__)
47#define DISPENSO_HAS_TIMESTAMP
48uint64_t rdtscp(
void) {
50 __asm__
volatile(
"mrs %0, cntvct_el0" :
"=r"(val));
56#if defined(DISPENSO_HAS_TIMESTAMP)
58static bool snapFreq(
double& firstApprox) {
59 switch (
static_cast<int>(firstApprox)) {
61 if (std::abs(
int(firstApprox * 10.0)) <= 1) {
67 if (std::abs(
int(firstApprox * 10.0) - 99) <= 1) {
74 if (std::abs(
int(firstApprox * 10.0) - 33) <= 1) {
75 firstApprox = 3.0 + 1.0 / 3.0;
80 if (std::abs(
int(firstApprox * 10.0) - 66) <= 1) {
81 firstApprox = 6.0 + 2.0 / 3.0;
89static double fallbackTicksPerSecond() {
90 using namespace std::chrono_literals;
91 constexpr double kChronoOverheadBias = 250e-9;
93 auto baseStart = std::chrono::high_resolution_clock::now();
94 auto start = rdtscp();
95 std::this_thread::sleep_for(50ms);
97 auto baseEnd = std::chrono::high_resolution_clock::now();
99 auto base = std::chrono::duration<double>(baseEnd - baseStart).count() - kChronoOverheadBias;
100 double firstApprox = (
static_cast<double>(end - start)) / base;
109 int firstInt =
static_cast<int>(firstApprox);
110 firstApprox -= firstInt;
114 if (!snapFreq(firstApprox)) {
115 int secondInt =
static_cast<int>(firstApprox);
116 firstApprox -= secondInt;
118 snapFreq(firstApprox);
120 firstApprox += secondInt;
125 firstApprox += firstInt;
131static double ticksPerSecond() {
132 mach_timebase_info_data_t info;
133 if (mach_timebase_info(&info) != KERN_SUCCESS) {
134 return fallbackTicksPerSecond();
136 return 1e9 *
static_cast<double>(info.denom) /
static_cast<double>(info.numer);
139double ticksPerSecond() {
140 return fallbackTicksPerSecond();
145 static double secondsPerTick = 1.0 / ticksPerSecond();
146 static double startTime =
static_cast<double>(rdtscp()) * secondsPerTick;
148 double t =
static_cast<double>(rdtscp()) * secondsPerTick;
149 return t - startTime;
153 static auto startTime = std::chrono::high_resolution_clock::now();
154 auto cur = std::chrono::high_resolution_clock::now();
156 return std::chrono::duration<double>(cur - startTime).count();
162double g_dummyTime = getTime();