// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #pragma once #include #include #include #include constexpr unsigned kWarmUpIterations = 10; // N.B. This value can't be so large that the buffer fills in oneshot mode. // The benchmark will assert-fail if the buffer fills: Otherwise the benchmark // is invalid. constexpr unsigned kDefaultRunIterations = 100000; // The number of test runs to do. // We do this many runs and report min,max,average. // We do this because there's some variability in the runs, and this helps // identify when it's happening and cope. constexpr unsigned kNumTestRuns = 10; // Measures how long it takes to run some number of iterations of a closure. // Returns a value in microseconds. template float Measure(unsigned iterations, const T& closure) { zx_ticks_t start = zx_ticks_get(); for (unsigned i = 0; i < iterations; ++i) { closure(); } zx_ticks_t stop = zx_ticks_get(); return (static_cast(stop - start) * 1000000.f / static_cast(zx_ticks_per_second())); } using thunk = fbl::Function; // Runs a closure repeatedly and prints its timing. template void RunAndMeasure(const char* test_name, const char* spec_name, unsigned iterations, const T& closure, thunk setup, thunk teardown) { printf("\n* %s: %s ...\n", spec_name, test_name); setup(); float warm_up_time = Measure(kWarmUpIterations, closure); teardown(); printf(" - warm-up: %u iterations in %.3f us, %.3f us per iteration\n", kWarmUpIterations, warm_up_time, warm_up_time / kWarmUpIterations); float run_times[kNumTestRuns]; for (unsigned i = 0; i < kNumTestRuns; ++i) { setup(); run_times[i] = Measure(iterations, closure); teardown(); zx::nanosleep(zx::deadline_after(zx::msec(10))); } float min = 0, max = 0; float cumulative = 0; for (const auto rt : run_times) { if (min == 0 || min > rt) min = rt; if (max == 0 || max < rt) max = rt; cumulative += rt; } float average = cumulative / kNumTestRuns; printf(" - run: %u test runs, %u iterations per run\n", kNumTestRuns, iterations); printf(" - total (usec): min: %.3f, max: %.3f, ave: %.3f\n", min, max, average); printf(" - per-iteration (usec): min: %.3f\n", // The static cast is to avoid a "may change value" warning. min / static_cast(iterations)); } template void RunAndMeasure(const char* test_name, const char* spec_name, const T& closure, thunk setup, thunk teardown) { RunAndMeasure(test_name, spec_name, kDefaultRunIterations, closure, fbl::move(setup), fbl::move(teardown)); }