// 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 <stdio.h>
#include <fbl/function.h>

#include <zircon/syscalls.h>
#include <lib/zx/time.h>

#include <utility>

// Lines of text for each result are prefixed with this.
constexpr const char* kTestOutputPrefix = "  - ";

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 <typename T>
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<float>(stop - start) * 1000000.f /
            static_cast<float>(zx_ticks_per_second()));
}

using thunk = fbl::Function<void ()>;

// Runs a closure repeatedly and prints its timing.
template <typename T>
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("%swarm-up: %u iterations in %.3f us, %.3f us per iteration\n",
           kTestOutputPrefix, 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("%srun: %u test runs, %u iterations per run\n",
           kTestOutputPrefix, kNumTestRuns, iterations);
    printf("%stotal (usec): min: %.3f, max: %.3f, ave: %.3f\n",
           kTestOutputPrefix, min, max, average);
    printf("%sper-iteration (usec): min: %.3f\n",
           // The static cast is to avoid a "may change value" warning.
           kTestOutputPrefix, min / static_cast<float>(iterations));
}

template <typename T>
void RunAndMeasure(const char* test_name, const char* spec_name,
                   const T& closure, thunk setup, thunk teardown) {
    RunAndMeasure(test_name, spec_name, kDefaultRunIterations, closure,
                  std::move(setup), std::move(teardown));
}
