-
-
Save Tillsunset/61d8681c7b681b8f0922fca068db6ca1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <chrono> | |
#include <ctime> | |
#include <cpuid.h> | |
#include <iostream> | |
#include <unistd.h> | |
int iterations = 10000000; | |
#define approxMono CLOCK_MONOTONIC_RAW_APPROX | |
inline void cpuid(int cpuInfo[4], int functionId) { | |
__cpuid(functionId, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]); | |
} | |
int main() | |
{ | |
// start of dummy run for first time slowdown | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::steady_clock::time_point(std::chrono::nanoseconds(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW))); | |
} | |
struct timespec tpMonoAprDummy; | |
for (int i = 0; i < iterations; ++i) { | |
clock_gettime(approxMono, &tpMonoAprDummy); | |
std::chrono::steady_clock::time_point( | |
std::chrono::seconds(tpMonoAprDummy.tv_sec) + std::chrono::nanoseconds(tpMonoAprDummy.tv_nsec)); | |
} | |
struct timespec tpMonoRawDummy; | |
for (int i = 0; i < iterations; ++i) { | |
clock_gettime(CLOCK_MONOTONIC_RAW, &tpMonoRawDummy); | |
std::chrono::steady_clock::time_point( | |
std::chrono::seconds(tpMonoRawDummy.tv_sec) + std::chrono::nanoseconds(tpMonoRawDummy.tv_nsec)); | |
} | |
struct timespec tpMonoDummy; | |
for (int i = 0; i < iterations; ++i) { | |
clock_gettime(CLOCK_MONOTONIC, &tpMonoDummy); | |
std::chrono::steady_clock::time_point( | |
std::chrono::seconds(tpMonoDummy.tv_sec) + std::chrono::nanoseconds(tpMonoDummy.tv_nsec)); | |
} | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::steady_clock::now(); | |
} | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::system_clock::now(); | |
} | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::high_resolution_clock::now(); | |
} | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::steady_clock::time_point( | |
std::chrono::nanoseconds(__rdtsc())); | |
} | |
// end of dummy run | |
auto startGetN = std::chrono::high_resolution_clock::now(); | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::steady_clock::time_point(std::chrono::nanoseconds(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW))); | |
} | |
auto stopGetN = std::chrono::high_resolution_clock::now(); | |
auto startMonoApx = std::chrono::high_resolution_clock::now(); | |
struct timespec tpMonoApr; | |
for (int i = 0; i < iterations; ++i) { | |
clock_gettime(approxMono, &tpMonoApr); | |
std::chrono::steady_clock::time_point( | |
std::chrono::seconds(tpMonoApr.tv_sec) + std::chrono::nanoseconds(tpMonoApr.tv_nsec)); | |
} | |
auto stopMonoApx = std::chrono::high_resolution_clock::now(); | |
auto startMonoRaw = std::chrono::high_resolution_clock::now(); | |
struct timespec tpMonoRaw; | |
for (int i = 0; i < iterations; ++i) { | |
clock_gettime(CLOCK_MONOTONIC_RAW, &tpMonoRaw); | |
std::chrono::steady_clock::time_point( | |
std::chrono::seconds(tpMonoRaw.tv_sec) + std::chrono::nanoseconds(tpMonoRaw.tv_nsec)); | |
} | |
auto stopMonoRaw = std::chrono::high_resolution_clock::now(); | |
auto startMono = std::chrono::high_resolution_clock::now(); | |
struct timespec tpMono; | |
for (int i = 0; i < iterations; ++i) { | |
clock_gettime(CLOCK_MONOTONIC, &tpMono); | |
std::chrono::steady_clock::time_point( | |
std::chrono::seconds(tpMono.tv_sec) + std::chrono::nanoseconds(tpMono.tv_nsec)); | |
} | |
auto stopMono = std::chrono::high_resolution_clock::now(); | |
auto startSteadyNow = std::chrono::high_resolution_clock::now(); | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::steady_clock::now(); | |
} | |
auto stopSteadyNow = std::chrono::high_resolution_clock::now(); | |
auto startSystemNow = std::chrono::high_resolution_clock::now(); | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::system_clock::now(); | |
} | |
auto stopSystemNow = std::chrono::high_resolution_clock::now(); | |
auto startHighResNow = std::chrono::high_resolution_clock::now(); | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::high_resolution_clock::now(); | |
} | |
auto stopHighResNow = std::chrono::high_resolution_clock::now(); | |
auto startRDTSC = std::chrono::high_resolution_clock::now(); | |
for (int i = 0; i < iterations; ++i) { | |
std::chrono::steady_clock::time_point( | |
std::chrono::nanoseconds(__rdtsc())); | |
} | |
auto stopRDTSC = std::chrono::high_resolution_clock::now(); | |
auto durationRDTSC = duration_cast<std::chrono::milliseconds>(stopRDTSC - startRDTSC); | |
auto durationGetN = duration_cast<std::chrono::milliseconds>(stopGetN - startGetN); | |
auto durationMono = duration_cast<std::chrono::milliseconds>(stopMono - startMono); | |
auto durationMonoRaw = duration_cast<std::chrono::milliseconds>(stopMonoRaw - startMonoRaw); | |
auto durationMonoApx = duration_cast<std::chrono::milliseconds>(stopMonoApx - startMonoApx); | |
auto durationSteadyNow = duration_cast<std::chrono::milliseconds>(stopSteadyNow - startSteadyNow); | |
auto durationSystemNow = duration_cast<std::chrono::milliseconds>(stopSystemNow - startSystemNow); | |
auto durationHighResNow = duration_cast<std::chrono::milliseconds>(stopHighResNow - startHighResNow); | |
int cpuInfo[4]; | |
cpuid(cpuInfo, 0x80000007); | |
printf("********** Testing different clock sources **********\n"); | |
std::cout << "Time taken by RDTSC: " << durationRDTSC.count() << " milliseconds, is Steady " << ((cpuInfo[3] >> 8) & 1) << std::endl; | |
std::cout << "Time taken by MonoApx: " << durationMonoApx.count() << " milliseconds, is Steady: " << true << std::endl; // cached MonoRaw | |
std::cout << "Time taken by gettime_nsec: " << durationGetN.count() << " milliseconds, is Steady: " << true << std::endl; // optimized clock_gettime, probably macos only | |
std::cout << "Time taken by MonoRaw: " << durationMonoRaw.count() << " milliseconds, is Steady: " << true << std::endl; | |
std::cout << "Time taken by Mono: " << durationMono.count() << " milliseconds, is Steady: " << false << std::endl; | |
std::cout << "Time taken by system_clock: " << durationSystemNow.count() << " milliseconds, is Steady " << std::chrono::system_clock::is_steady << std::endl; | |
std::cout << "Time taken by steady_clock: " << durationSteadyNow.count() << " milliseconds, is Steady " << std::chrono::steady_clock::is_steady << std::endl; | |
std::cout << "Time taken by highres: " << durationHighResNow.count() << " milliseconds, is Steady " << std::chrono::high_resolution_clock::is_steady << std::endl; //typically alias of steady_ or system_clock | |
signed long long max = 0; | |
signed long long min = 1000000; | |
signed long long avgDist = 0; | |
signed long long avgDiff = 0; | |
signed long long temp = 0; | |
for (int i = 0; i < iterations; ++i) { | |
temp = ((signed long long)(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) - clock_gettime_nsec_np(approxMono))); | |
avgDiff += temp; | |
max = temp > max ? temp : max; | |
min = temp < min ? temp : min; | |
avgDist += temp > 0 ? temp : -temp; | |
} | |
avgDist /= iterations; | |
avgDiff /= iterations; | |
printf("\n********** Testing CLOCK_MONOTONIC_RAW and approxMono **********\n"); | |
printf("max behind between raw and approx: %lld nanoseconds\n", min); | |
printf("max ahead between raw and approx: %lld nanoseconds\n", max); | |
printf("avg distance between raw and approx: %lld nanoseconds\n", avgDist); | |
printf("avg difference between raw and approx: %lld nanoseconds\n", avgDiff); | |
unsigned long long lastApx = clock_gettime_nsec_np(approxMono); | |
unsigned long long BeforeRaw = 0; | |
unsigned long long totalRawDiff = 0; | |
unsigned long long maxRawDiff = 0; | |
unsigned long long minRawDiff = 1000000; | |
unsigned long long tempDiff = 0; | |
int updateCounts = 0; | |
for (int i = 0; i < iterations * 5;) { | |
BeforeRaw = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW); | |
while (clock_gettime_nsec_np(approxMono) == lastApx) { | |
i++; | |
} | |
lastApx = clock_gettime_nsec_np(approxMono); | |
tempDiff = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) - BeforeRaw; | |
totalRawDiff += tempDiff; | |
maxRawDiff = tempDiff > maxRawDiff ? tempDiff : maxRawDiff; | |
minRawDiff = tempDiff < minRawDiff ? tempDiff : minRawDiff; | |
updateCounts++; | |
} | |
printf("\n********** Testing approxMono update intervals **********\n"); | |
printf("max time to change: %lld nanoseconds\n", maxRawDiff); | |
printf("min time to change: %lld nanoseconds\n", minRawDiff); | |
printf("avg time to change: %lld nanoseconds\n", totalRawDiff/updateCounts); | |
printf("updateCounts: %d\n", updateCounts); | |
printf("total: %lld nanoseconds\n", totalRawDiff); | |
unsigned long long before = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW); | |
unsigned long long beforeRDTSC = __rdtsc(); | |
sleep(1); | |
unsigned long long after = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW); | |
unsigned long long afterRDTSC = __rdtsc(); | |
printf("\none sec gettime_nsec: %llu nanoseconds\n", after - before); | |
printf("\none sec rdtsc: %llu nanoseconds\n", afterRDTSC - beforeRDTSC); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
********** Testing different clock sources **********
Time taken by RDTSC: 68 milliseconds, is Steady 1
Time taken by MonoApx: 170 milliseconds, is Steady: 1
Time taken by gettime_nsec: 366 milliseconds, is Steady: 1
Time taken by MonoRaw: 413 milliseconds, is Steady: 1
Time taken by Mono: 737 milliseconds, is Steady: 0
Time taken by system_clock: 263 milliseconds, is Steady 0
Time taken by steady_clock: 424 milliseconds, is Steady 1
Time taken by highres: 426 milliseconds, is Steady 1
********** Testing CLOCK_MONOTONIC_RAW and approxMono **********
max behind between raw and approx: -57726 nanoseconds
max ahead between raw and approx: 1022797 nanoseconds
avg distance between raw and approx: 293859 nanoseconds
avg difference between raw and approx: 293858 nanoseconds
********** Testing approxMono update intervals **********
max time to change: 1021101 nanoseconds
min time to change: 61 nanoseconds
avg time to change: 36711 nanoseconds
updateCounts: 19446
total: 713886635 nanoseconds
one sec gettime_nsec: 1003264331 nanoseconds
one sec rdtsc: 1396543980 nanoseconds