我正在尝试std::isdigit
从标头中对函数进行基准测试(为了清楚起见,从Ccctype
继承的函数)。
代码片段如下:
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);
很容易推断这GenerateRandomChar
是一个简单的函数,它会生成随机数char
,并且不会给基准测试本身带来任何开销。
"""不幸的是""",编译器能够完全优化代码。它正确地生成了预期的代码std::isdigit
,但是,在基准测试的汇编代码中,基本块被忽略了。
以下是分析生成的代码(由gcc-10.1.0):
如您所见,std::isdigit
代码已生成(编译器资源管理器示例):
movzbl %r13b,%eax
sub $0x30,%eax
cmp $0x9,%eax
setbe %al
movzbl %al,%eax
但由于空循环,它被完全忽略:
68: sub $0x1,%rbx <---|
jne 68 ------|
小笔记
“ C++版本”(带语言环境)生成预期代码:测试函数代码的循环。
我的问题是:
- 为什么
benchmark::DoNotOptimize
不适用于此特定功能? - 我如何更改基准代码以正确测量该功能的时间性能?
- 我在
clang
编译器上遇到了同样的“问题”。 - 我试图将测试的函数“移动”到另一个翻译单元(强制非内联属性),但我遇到了同样的“问题”。