因为 Quick C++ Benchmarks
例。
static void StringCopyFromLiteral(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
std::string from_literal("hello");
// Make sure the variable is not optimized away by compiler
benchmark::DoNotOptimize(from_literal);
}
}
// Register the function as a benchmark
BENCHMARK(StringCopyFromLiteral);
static void StringCopyFromString(benchmark::State& state) {
// Code before the loop is not measured
std::string x = "hello";
for (auto _ : state) {
std::string from_string(x);
}
}
// Register the function as a benchmark
BENCHMARK(StringCopyFromString);
http:/quick-bench.comIcZllt_14hTeMaB_sBZ0CQ8x2Ro。
如果我懂组装怎么办...
更多结果。
答案很简单。在你构造一个 std::string
在这种情况下,编译器通过使用汇编中的常量直接填充字符串对象的内容进行优化。 这避免了昂贵的循环以及测试是否可以应用小字符串优化(SSO)。 在这种情况下,它知道可以应用SSO,所以编译器生成的代码只需要将字符串直接写入SSO缓冲区。
注意StringCreation案例中的这段汇编代码。
// Populate SSO buffer (each set of 4 characters is backwards since
// x86 is little-endian)
19.63% movb $0x6f,0x4(%r15) // "o"
19.35% movl $0x6c6c6568,(%r15) // "lleh"
// Set size
20.26% movq $0x5,0x10(%rsp) // size = 5
// Probably set heap pointer. 0 (nullptr) = use SSO buffer
20.07% movb $0x0,0x1d(%rsp)
你看到的是那里的常量值。这段代码不多,也不需要循环。 事实上,在StringCreation中的 std::string
构造者 甚至不需要被调用! 编译器只是把东西放在内存里,放在与 std::string
构造函数会。
如果编译器不能应用这种优化,结果就会大不相同--特别是,如果我们通过先将字词复制到一个char数组中来 "隐藏 "源是字符串字词的事实,结果就会翻转。
char x[] = "hello";
for (auto _ : state) {
std::string created_string(x);
benchmark::DoNotOptimize(created_string);
}
现在,"from-char-pointer "的情况下,会采取 两倍! ! - 为什么?
I 怀疑 这是因为 "copy from char pointer "的情况下,不能简单地通过查看一个值来检查字符串有多长。 它需要知道是否可以进行小字符串优化。 它有几种方法可以去做。
对比一下,当它从另一个字符串对象中复制时的情况:它可以简单地看一下 size()
的另一个字符串,并立即知道它是否可以进行SSO,如果不能进行SSO,那么它也知道到底要为新字符串分配多少内存。