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)
58#if !defined(__aarch64__)
60static bool snapFreq(
double& firstApprox) {
61 switch (
static_cast<int>(firstApprox)) {
63 if (std::abs(
int(firstApprox * 10.0)) <= 1) {
69 if (std::abs(
int(firstApprox * 10.0) - 99) <= 1) {
76 if (std::abs(
int(firstApprox * 10.0) - 33) <= 1) {
77 firstApprox = 3.0 + 1.0 / 3.0;
82 if (std::abs(
int(firstApprox * 10.0) - 66) <= 1) {
83 firstApprox = 6.0 + 2.0 / 3.0;
91static double fallbackTicksPerSecond() {
92 using namespace std::chrono_literals;
93 constexpr double kChronoOverheadBias = 250e-9;
95 auto baseStart = std::chrono::high_resolution_clock::now();
96 auto start = rdtscp();
97 std::this_thread::sleep_for(50ms);
99 auto baseEnd = std::chrono::high_resolution_clock::now();
101 auto base = std::chrono::duration<double>(baseEnd - baseStart).count() - kChronoOverheadBias;
102 double firstApprox = (
static_cast<double>(end - start)) / base;
111 int firstInt =
static_cast<int>(firstApprox);
112 firstApprox -= firstInt;
116 if (!snapFreq(firstApprox)) {
117 int secondInt =
static_cast<int>(firstApprox);
118 firstApprox -= secondInt;
120 snapFreq(firstApprox);
122 firstApprox += secondInt;
127 firstApprox += firstInt;
133#if defined(__aarch64__)
134static double ticksPerSecond() {
136 __asm__
volatile(
"mrs %0, cntfrq_el0" :
"=r"(val));
137 return static_cast<double>(val);
139#elif defined(__MACH__)
140static double ticksPerSecond() {
141 mach_timebase_info_data_t info;
142 if (mach_timebase_info(&info) != KERN_SUCCESS) {
143 return fallbackTicksPerSecond();
145 return 1e9 *
static_cast<double>(info.denom) /
static_cast<double>(info.numer);
148double ticksPerSecond() {
149 return fallbackTicksPerSecond();
154 static double secondsPerTick = 1.0 / ticksPerSecond();
155 static double startTime =
static_cast<double>(rdtscp()) * secondsPerTick;
157 double t =
static_cast<double>(rdtscp()) * secondsPerTick;
158 return t - startTime;
162 static auto startTime = std::chrono::high_resolution_clock::now();
163 auto cur = std::chrono::high_resolution_clock::now();
165 return std::chrono::duration<double>(cur - startTime).count();
171double g_dummyTime = getTime();