首页 > 解决方案 > `static` 的使用如何影响我的代码速度?

问题描述

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

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

从此基准循环调用:

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);
  }
}

只是出于好奇,我做了一个基准测试

当我这样做时,我决定static从中删除process_valuevoid inline process_value否则它是一样的。令我惊讶的是,它变慢了。

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

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


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

标签: c++performancestaticclangbenchmarking

解决方案


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

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

void call();

inline void a() {
    call();
}

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

void foo() {
    a();
    b();
}

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

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

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

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

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

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

这是您的案例的数字,链接

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

process_valueS()::成本=-14600,阈值=325 -> 可以内联

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

提示:如果你想强制 clang 内联一个函数,使用__attribute__((always_inline))它。


推荐阅读