`static` 的使用如何影响我的代码速度?

Pab*_*hes 7 c++ performance benchmarking static clang

我正在在线解决一个练习,有一次我需要从字符串的开头和结尾删除“”。这是我的代码:

void static inline process_value(std::string &value) {
    if (value.back() !='>') {
        value = value.substr(1, value.size()-2);
    }
}
Run Code Online (Sandbox Code Playgroud)

从此基准循环调用:

static void UsingStatic(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
      std::string valor("\"Hola\"");
      process_valueS(valor);
    // Make sure the variable is not optimized away by compiler
    benchmark::DoNotOptimize(valor);
  }
}
Run Code Online (Sandbox Code Playgroud)

只是因为好奇,我做了一个基准测试

  • 编译器: Clang-9.0
  • 标准: C++20
  • 优化: O3
  • STL: libstdc++(GNU)

当我在这,我决定删除staticprocess_value,使void inline process_value这是其它方面相同。令我惊讶的是,它变慢了。

我认为 static 仅意味着该函数仅用于文件。但在这里它说“'静态'意味着如果可能的话,编译器应该内联该函数”。但是在那种情况下,当我删除 static 时,我认为结果不应该改变。现在我很困惑,除了将函数分隔为单个之外.cpp,静态还做了什么其他事情,这如何影响性能?

QuickBench 上的反汇编表明NoUsingStatic循环实际上是调用process_value而不是内联它,尽管inline关键字使编译器这样做是合法的。但是UsingStatic 确实内联了对process_valueS. 编译器决策的差异大概解释了性能的差异,但是为什么 clang 会选择不内联声明的简单函数void inline process_value(std::string &value){ ... }


编辑:因为问题被关闭,因为它不够清楚,我删除了与问题无关的部分。但如果我遗漏了一些信息,请在评论中告诉我

gez*_*eza 6

Clang 使用基于成本的决定是否将内联函数。这个成本受很多东西的影响。它受 影响static

幸运的是,clang 有一个输出,我们可以在其中观察到这一点。看看这个godbolt链接

void call();

inline void a() {
    call();
}

static inline void b() {
    call();
}

void foo() {
    a();
    b();
}
Run Code Online (Sandbox Code Playgroud)

在这个小例子中,a()b()都是一样的,唯一的例外b()是静态的。

如果您将鼠标移到通话a()b()Godbolt 上(在OptViewer窗口中),您可以阅读:

a():成本=0,阈值=487

b():成本=-15000,阈值=487

(如果成本小于阈值,clang 将内联调用。)

clang 的b()成本要低得多,因为它是静态的。似乎 clang 只会为静态函数降低 -15000 的成本。如果b()被多次调用b(),除了 1 之外,所有s的成本都为零。

以下是您的案例编号,链接

process_value(): cost=400, threshold=325 -> 刚好在阈值之上,不会被内联

process_valueS():: cost=-14600, threshold=325 -> 可以内联

因此,static如果只调用一次,显然会产生很大的影响。这是有道理的,因为内联静态函数一次不会增加代码大小。

提示:如果要强制 clang 内联函数,请使用__attribute__((always_inline))on 。