| #ifndef BENCHMARK_H | |
| #define BENCHMARK_H | |
| #include <limits> | |
| // Benchmark the operation 'op'. The number of iterations refers to | |
| // how many times the operation is run for each time measurement, the | |
| // result is the minimum over a number of samples runs. The result is the | |
| // amount of time in seconds for one iteration. | |
| #ifdef _WIN32 | |
| union _LARGE_INTEGER; | |
| typedef union _LARGE_INTEGER LARGE_INTEGER; | |
| extern "C" int __stdcall QueryPerformanceCounter(LARGE_INTEGER*); | |
| extern "C" int __stdcall QueryPerformanceFrequency(LARGE_INTEGER*); | |
| template <typename F> | |
| double benchmark(int samples, int iterations, F op) { | |
| int64_t freq; | |
| QueryPerformanceFrequency((LARGE_INTEGER*)&freq); | |
| double best = std::numeric_limits<double>::infinity(); | |
| for (int i = 0; i < samples; i++) { | |
| int64_t t1; | |
| QueryPerformanceCounter((LARGE_INTEGER*)&t1); | |
| for (int j = 0; j < iterations; j++) { | |
| op(); | |
| } | |
| int64_t t2; | |
| QueryPerformanceCounter((LARGE_INTEGER*)&t2); | |
| double dt = (t2 - t1) / static_cast<double>(freq); | |
| if (dt < best) best = dt; | |
| } | |
| return best / iterations; | |
| } | |
| #else | |
| #include <chrono> | |
| template <typename F> | |
| double benchmark(int samples, int iterations, F op) { | |
| double best = std::numeric_limits<double>::infinity(); | |
| for (int i = 0; i < samples; i++) { | |
| auto t1 = std::chrono::high_resolution_clock::now(); | |
| for (int j = 0; j < iterations; j++) { | |
| op(); | |
| } | |
| auto t2 = std::chrono::high_resolution_clock::now(); | |
| double dt = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() / 1e6; | |
| if (dt < best) best = dt; | |
| } | |
| return best / iterations; | |
| } | |
| #endif | |
| #endif |