Search code examples
c++google-benchmark

What happens to the return values while using Google benchmark?


I am benchmarking some functions in our software using the Google-benchmark. Let us say the function signature is something like below. The return type can be any other derived data type.

std::map<uint32_t, bool> func(Obj& o1, Obj& o2);

The benchmark function looks something like this.

static void BM_Func(benchmark::State& state) {

// Prepare the objects o1 and o2
for (auto _ : state)
  func(Obj& o1, Obj& o2);
}
BENCHMARK(BM_Func);

BENCHMARK_MAIN();

Now, the code compiles and I am able to collect the benchmark results. However, I have below questions.

  1. What happens to the return values? Should I be bothered at all if I am not using these values anywhere again in the benchmark function?
  2. Should I call the function instead like this benchmark::DoNotOptimize( func(Obj& o1, Obj& o2) ); to avoid optimization? I do not really understand when to call the function with benchmark::DoNotOptimize

Solution

  • The danger with not using benchmark::DoNotOptimize is that the compiler might realize that func has absolutely no side effects. It would then correctly conclude that your code is equivalent to for (auto _ : state) /* do nothing */;. You of course didn't want to measure nothing.

    Using benchmark::DoNotOptimize prevents the compiler from the above realization. It has no choice but to actually call func to obtain a result object (although the same considerations apply - if it can inline func and func always returns e.g. true, then the rest of func might get optimized out).

    If the returned object is large, then destructing it might take a meaningful amount of time. Since this happens inside the benchmarking loop in your code, this time will be included in your benchmark. Avoiding that is pretty nontrivial though, and any "real" user of the function will have to incur this time too, so the answer is "nothing extraordinary happens with those objects".