Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 49 additions & 3 deletions src/include/nanobench.h
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,24 @@ class Bench {
ANKERL_NANOBENCH(NOINLINE)
Bench& run(Op&& op);

/**
* @brief Runs a benchmark with a name, a setup, an operation, and a teardown. This is the core implementation.
* @tparam SetupOp A callable that is run once before each measurement.
* @tparam Op The code to benchmark.
* @tparam TeardownOp A callable that is run once after each measurement.
*/
template <typename SetupOp, typename Op, typename TeardownOp>
ANKERL_NANOBENCH(NOINLINE)
Bench& run(char const* benchmarkName, SetupOp&& setup, Op&& op, TeardownOp&& teardown);

template <typename SetupOp, typename Op, typename TeardownOp>
ANKERL_NANOBENCH(NOINLINE)
Bench& run(std::string const& benchmarkName, SetupOp&& setup, Op&& op, TeardownOp&& teardown);

template <typename SetupOp, typename Op, typename TeardownOp>
ANKERL_NANOBENCH(NOINLINE)
Bench& run(SetupOp&& setup, Op&& op, TeardownOp&& teardown);

/**
* @brief Title of the benchmark, will be shown in the table header. Changing the title will start a new markdown table.
*
Expand Down Expand Up @@ -1207,29 +1225,49 @@ constexpr uint64_t Rng::rotl(uint64_t x, unsigned k) noexcept {
return (x << k) | (x >> (64U - k));
}

template <typename Op>
template <typename SetupOp, typename Op, typename TeardownOp>
ANKERL_NANOBENCH_NO_SANITIZE("integer")
Bench& Bench::run(Op&& op) {
Bench& Bench::run(SetupOp&& setup, Op&& op, TeardownOp&& teardown) {
// It is important that this method is kept short so the compiler can do better optimizations/ inlining of op()
detail::IterationLogic iterationLogic(*this);
auto& pc = detail::performanceCounters();

while (auto n = iterationLogic.numIters()) {
setup();
pc.beginMeasure();
Clock::time_point const before = Clock::now();
while (n-- > 0) {
op();
}
Clock::time_point const after = Clock::now();
pc.endMeasure();
teardown();
pc.updateResults(iterationLogic.numIters());
iterationLogic.add(after - before, pc);
}
iterationLogic.moveResultTo(mResults);
return *this;
}

template <typename SetupOp, typename Op, typename TeardownOp>
Bench& Bench::run(char const* benchmarkName, SetupOp&& setup, Op&& op, TeardownOp&& teardown) {
name(benchmarkName);
return run(std::forward<SetupOp>(setup), std::forward<Op>(op), std::forward<TeardownOp>(teardown));
}

template <typename SetupOp, typename Op, typename TeardownOp>
Bench& Bench::run(std::string const& benchmarkName, SetupOp&& setup, Op&& op, TeardownOp&& teardown) {
name(benchmarkName);
return run(std::forward<SetupOp>(setup), std::forward<Op>(op), std::forward<TeardownOp>(teardown));
}


// Performs all evaluations.
template <typename Op>
Bench& Bench::run(Op&& op) {
return run([]{}, std::forward<Op>(op), []{});
}

template <typename Op>
Bench& Bench::run(char const* benchmarkName, Op&& op) {
name(benchmarkName);
Expand Down Expand Up @@ -2495,7 +2533,7 @@ class LinuxPerformanceCounters {
return x;
}

template <typename Op>
template <typename SetupOp, typename Op, typename TeardownOp>
ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")
void calibrate(Op&& op) {
// clear current calibration data,
Expand All @@ -2509,9 +2547,11 @@ class LinuxPerformanceCounters {
v = (std::numeric_limits<uint64_t>::max)();
}
for (size_t iter = 0; iter < 100; ++iter) {
setup();
beginMeasure();
op();
endMeasure();
teardown();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please add a test which makes sure the setup and teardown costs aren't included in the measurements?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it myself in #136 with a different implementation

if (mHasError) {
return;
}
Expand Down Expand Up @@ -2565,6 +2605,12 @@ class LinuxPerformanceCounters {
}
}

template <typename Op>
ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")
void calibrate(Op&& op) {
calibrate([]{}, std::forward<Op>(op), []{});
}

private:
bool monitor(uint32_t type, uint64_t eventid, Target target);

Expand Down