blob: 980dc31bb001d6e8d8367b6eb4520c6b9f00f30f [file] [log] [blame] [edit]
/*
* Copyright 2022 Rive
*/
#include "bench.hpp"
#include <chrono>
#include <string.h>
// Run a microbenchmark repeatedly for a few seconds and print the quickest
// time.
#ifdef __EMSCRIPTEN__
int rive_wasm_main(int argc, const char* const* argv)
#else
int main(int argc, const char** argv)
#endif
{
using namespace std::chrono_literals;
using clock = std::chrono::high_resolution_clock;
// Default flags.
clock::duration benchDuration = 5s;
// Parse flags.
const char* const* arg = argv + 1;
const char* const* endarg = argv + argc;
while (arg + 1 < endarg && *arg[0] == '-')
{
if (!strcmp(*arg, "--duration") || !strcmp(*arg, "-d"))
{
benchDuration = std::chrono::seconds(atoi(arg[1]));
}
arg += 2;
}
// Find the selected benchmark.
Bench::BenchMap& registry = Bench::Registry();
const char* benchName = arg < endarg ? *arg : "";
auto benchIter = registry.find(benchName);
if (benchIter == registry.end())
{
// Print out the usage unless they ran "bench list".
if (arg >= endarg || !!strcmp(*arg, "list"))
{
fprintf(stderr,
"Usage:\n\nbench [--duration <seconds>] <benchmark>\n\n");
fprintf(stderr, "Benchmarks:\n\n");
fflush(stderr);
}
// Print out the benchmarks.
for (const auto& [name, constructor] : registry)
{
printf("%s ", name.c_str());
}
printf("\n");
fflush(stdout);
return 1;
}
// Run the benchmark.
auto constructor = benchIter->second;
std::unique_ptr<Bench> bench(constructor());
bench->setup();
clock::duration minTime = clock::duration::max();
clock::time_point quitTime = clock::now() + benchDuration;
clock::time_point start, end;
do
{
start = clock::now();
bench->run();
end = clock::now();
minTime = std::min(end - start, minTime);
} while (end < quitTime);
#ifdef DEBUG
printf("<time hidden in debug builds> %s\n", benchName);
#else
printf("%.4gms %s\n",
std::chrono::nanoseconds(minTime).count() * 1e-6,
benchName);
#endif
return 0;
}