为什么这些创建字符串的方法之间有如此大的差异

时间:2019-12-10 16:49:13

标签: c++ string gcc

我正在浏览一个站点,以优化和性能为目的对c ++中的小函数和方法进行基准测试,结果发现一些关于字符串的结果,我无法弄清原因。 链接http://quick-bench.com/mNexo7ae75tYgt8HYoB17HEHgKc以获得基准代码。

static void StringCreation(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
    std::string created_string("hello");
    // Make sure the variable is not optimized away by compiler
    benchmark::DoNotOptimize(created_string);
  }
}
// Register the function as a benchmark
BENCHMARK(StringCreation);

static void StringCreationMove(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  std::string x = "hello";
  for (auto _ : state) {
    std::string created_string_move(std::move(x));
    // Make sure the variable is not optimized away by compiler
    benchmark::DoNotOptimize(created_string_move);
  }
}
// Register the function as a benchmark
BENCHMARK(StringCreationMove);

static void StringCopy(benchmark::State& state) {
  // Code before the loop is not measured
  std::string x = "hello";
  for (auto _ : state) {
    std::string copy(x.c_str());
    benchmark::DoNotOptimize(copy);
  }
}
BENCHMARK(StringCopy);

static void StringCopyByChar(benchmark::State& state) {
  // Code before the loop is not measured
  const char* x = "hello";
  for (auto _ : state) {
    std::string copyChar(x);
    benchmark::DoNotOptimize(copyChar);
  }
}
BENCHMARK(StringCopyByChar);

enter image description here

1 个答案:

答案 0 :(得分:2)

字符串的长度将对特定结果产生重大影响,同时还会影响任何小的字符串优化。例如,即使是“移动”,它也可能强制执行“逐字节复制”,同时避免了为其他操作分配任何内存的成本。

也不太确定自己的期望。

  

静态无效的StringCreation

在没有优化的情况下,这里可能需要确定每次迭代的长度,因为您给它提供了一个空终止的字符串,基本上是一个额外的strlen调用。

但是,当有效地看到strlen("literal string")并分配固定长度的副本时,有可能对该模式进行了优化,甚至可能由于SSO而跳过了分配,只剩下了将某些字段分配给常量值。

GCC和Clang似乎可以做到这一点,我无法让MSVC v142(2019)使用默认的/ O2发布项目来做到这一点,它优化了“ strlen”而不是分配本身。

  

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

这将使字符串远离第一个循环后处于未指定状态的字符串,因此可以执行从无操作到复制整个字符串的任何操作。这可能取决于字符串的长度,而该实现的字符串优化很小。

  

静态void StringCopy(benchmark :: State&state){

通过传递c_str()就像第一种情况一样,但是假设在标准的约束范围内甚至有可能,任何编译器都不太可能找出固定长度并对其进行优化。

  

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

这与第一种情况类似,编译器可能会发现您的const char将始终相同。