I am trying to benchmark the function std::isdigit
from the header cctype
(the one inherited from C, just to be clear).
The code snippet is the following:
void BM_IsDigit_C(::benchmark::State& state) {
const char c = GenerateRandomChar();
for (auto _ : state) {
::benchmark::DoNotOptimize(std::isdigit(static_cast<unsigned char>(c)));
}
}
BENCHMARK(BM_IsDigit_C);
It's quite easy to deduct that GenerateRandomChar
is a simple function which generates a random char
and should bring no overhead into the benchmark itself.
"""Unfortunately""", the compiler is able to completely optimize the code. It correctly generates the expected code for std::isdigit
, but, in the assembly code of the benchmark the basic block is ignored.
The following is the profiled generated code (by gcc-10.1.0):
As you can see, the std::isdigit
code is generated (compiler explorer example):
movzbl %r13b,%eax
sub $0x30,%eax
cmp $0x9,%eax
setbe %al
movzbl %al,%eax
But it is completely ignored because of the empty loop:
68: sub $0x1,%rbx <---|
jne 68 ------|
Little Note
The "C++ version" (with locale) generates the expected code: the loop testing the function code.
My questions are:
- Why
benchmark::DoNotOptimize
does not work with this particular function? - How could I change the benchmark code in order to properly measure the time performance of that function?
- I got the same "problem" with
clang
compiler. - I tried to "move" the tested function into another translation unit (forcing the not-inline attribute), but I got the same "problem".