Created
July 30, 2018 22:18
-
-
Save kodejuice/8faaccb5b3384d3bbaaedcb134ba64be to your computer and use it in GitHub Desktop.
A minimal C++ code perfomance tester
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
/** | |
A minimal code perfomance tester for C++ that aids in measuring the execution speed of parts of your program, | |
it reports the (operatations per second) as opposed to the traditional (time taken to run) approach, | |
the programs repeatedly runs the given function for a couple of seconds, | |
and returns the number of operations it could perform in a single second (cycles per second). | |
See Example/Sample usage at bottom of code | |
*/ | |
#include <bits/stdc++.h> | |
using namespace std; | |
template <class T, class... Args> static int run_perft(T, Args...); | |
template <class T, class... Args> static void warm_up(string, T, Args...); | |
#define perft(n, x, args...) warm_up(n, x, args); | |
static double max_cps = 0; | |
static vector<double> cycles; | |
static vector<string> tests; | |
// warm up test function | |
template <class T, class... Args> | |
static void warm_up(string testname, T fn, Args... args) { | |
int cps = 0; | |
double clk = clock(); | |
while (((double(clock()) - clk)/CLOCKS_PER_SEC)*1e3 < 400) { | |
fn(args...); | |
} | |
cps = run_perft(fn, args...); // run test | |
cout << "\n+ " << testname << '\n'; | |
cout << " " << cps << " ops/second\n"; | |
cycles.push_back(cps); | |
tests.push_back(testname); | |
max_cps = std::max<double>(max_cps, cps); | |
} | |
// test runner | |
template <class T, class... Args> | |
static int run_perft(T fn, Args... args) { | |
int cycles = 0; | |
double clk = clock(); | |
while (((double(clock()) - clk)/CLOCKS_PER_SEC) < 3) { | |
fn(args...); | |
cycles += 1; | |
} | |
return cycles / 3; | |
} | |
// log perft stats | |
static void perft_stats() { | |
int c = 0; | |
streamsize def = cout.precision(2); | |
cout << '\n'; | |
for (auto v : cycles) { | |
if (v == max_cps) { | |
cout << tests[c] << " = fastest\n"; | |
} | |
else { | |
cout << tests[c] << " = " << (100-((v/max_cps)*100)) << "% slower\n"; | |
} | |
c += 1; | |
} | |
cout.precision(def); | |
max_cps = 0, cycles = {}, tests = {}; | |
} | |
////////////////// | |
// Simple usage // | |
////////////////// | |
// fibonacci iterative - test case 1 | |
int fibonacci_iterative(int n) { | |
if(n <= 1) return n; | |
int fib = 1, prevFib = 1, tmp; | |
for(int i=2; i<n; i++) { | |
tmp = fib; | |
fib += prevFib; | |
prevFib = tmp; | |
} | |
return fib; | |
} | |
// fibonacci recursive - test case 2 | |
int fibonacci_recursive(int n) { | |
if(n <= 1) return n; | |
return fibonacci_recursive(n-1) + fibonacci_recursive(n-2); | |
} | |
int main() { | |
int t = 10; | |
perft("fibonacci_iterative ", fibonacci_iterative, t); | |
perft("fibonacci_recursive ", fibonacci_recursive, t); | |
perft_stats(); | |
} | |
// Possible output | |
/* | |
+ fibonacci_iterative | |
1384161 ops/second | |
+ fibonacci_recursive | |
412086 ops/second | |
fibonacci_iterative = fastest | |
fibonacci_recursive = 70% slower | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment