简体   繁体   English

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

[英]How does the use of `static` affect the speed of my code?

I was solving an exercise online, and at one point i needed to delete the "" from a the beginning and end of a string.我正在在线解决一个练习,有一次我需要从字符串的开头和结尾删除“”。 This was my code:这是我的代码:

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

Called from this benchmark loop:从此基准循环调用:

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

Just because of curiosity I did a benchmark .只是出于好奇,我做了一个基准测试

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

While I was at it I decided to remove static from process_value , making void inline process_value that was otherwise the same.当我这样做时,我决定从process_value中删除static ,使void inline process_value在其他方面相同。 To my surprise it was slower.令我惊讶的是,它变慢了。

I thought that static only meant that the function was just for a file.我认为 static 仅意味着 function 仅用于文件。 But here it says that " 'static' means that the function should be inlined by the compiler if possible".但是这里它说“'静态'意味着 function 应该尽可能由编译器内联”。 But in that case when i removed static I think that the result should not have changed.但在那种情况下,当我删除 static 时,我认为结果不应该改变。 Now I'm am confused, what other things does static do other than delimiting the function to a single .cpp , how does that affect performance?现在我很困惑,除了将 function 分隔为单个.cpp之外,static 还能做什么,这对性能有何影响?

The disassembly on QuickBench shows that the NoUsingStatic loop actually calls process_value instead of inlining it, despite the inline keyword making it legal for the compiler to do so. QuickBench 上的反汇编显示NoUsingStatic循环实际上调用process_value而不是内联它,尽管inline关键字使编译器这样做是合法的。 But UsingStatic does inline the call to process_valueS .但是UsingStatic确实内联了对process_valueS的调用。 That difference in compiler decision-making presumably explains the difference in performance, but why would clang choose not to inline a simple function declared void inline process_value(std::string &value){... } ?编译器决策的差异大概解释了性能的差异,但为什么 clang 选择不内联一个简单的 function 声明为void inline process_value(std::string &value){... }


EDIT: Beacuse the question was closed because it was not clear enough, i deleted parts that where not related to the question.编辑:因为问题不够清楚,所以问题已关闭,我删除了与问题无关的部分。 But if im missing some information please tell me in the comments但如果我错过了一些信息,请在评论中告诉我

Clang uses a cost based decision whether a function will be inlined or not. Clang 使用基于成本的决定是否将 function 内联。 This cost is affected by a lot of things.这个成本受很多事情的影响。 It is affected by static .它受static影响。

Fortunately, clang has an output, where we can observe this.幸运的是,clang 有一个 output,我们可以在其中观察到这一点。 Check out this godbolt link :看看这个神螺栓链接

void call();

inline void a() {
    call();
}

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

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

In this little example, a() and b() are the same, the only exception is that b() is static.在这个小例子中, a()b()是相同的,唯一的例外是b()是 static。

If you move the mouse over the calls a() or b() on godbolt (in OptViewer window), you can read:如果您将鼠标移动到 Godbolt 上的调用a()b()上(在OptViewer窗口中),您可以阅读:

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

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

(clang will inline a call, if the cost is less than the threshold.) (如果成本低于阈值,clang 将内联调用。)

clang gave b() a much lower cost, because it is static. clang 给b()的成本要低得多,因为它是 static。 It seems that clang will only give this -15000 cost reduction for a static function only once.似乎 clang 只会为 static function 降低 -15000 的成本。 If b() is called several times, the cost of all b() s will be zero, except one.如果b()被多次调用,所有b()的成本将为零,除了一个。

Here are the numbers for your case, link :这是您的案例的数字,链接

process_value(): cost=400, threshold=325 -> it is just above the threshold, won't be inlined process_value(): cost=400, threshold=325 -> 刚好高于阈值,不会被内联

process_valueS(): : cost=-14600, threshold=325 -> OK to inline process_valueS(): : cost=-14600, threshold=325 -> OK to inline

So, apparently, static can have a lot of impact, if it is only called once.因此,显然,如果只调用一次static就会产生很大的影响。 Which makes sense, because inlining a static function once doesn't increase code size.这是有道理的,因为内联 static function 一次不会增加代码大小。

Tip: if you want to force clang to inline a function, use __attribute__((always_inline)) on it.提示:如果您想强制 clang 内联 function,请在其上使用__attribute__((always_inline))

inline is just an advise to the compiler, which may or may not really inline that your particular code. inline只是对编译器的一个建议,它可能会或可能不会真正内联您的特定代码。

Regarding to the static keyword, if it's applied to a global variable, then it has the file-scope (as you've mentioned) if you compile your code as a separate compilation-unit.关于static关键字,如果它应用于全局变量,那么如果您将代码编译为单独的编译单元,则它具有文件范围(正如您所提到的)。 So it's even possible to have your static global variables accessible from other files if you compile them as a single compilation unit.因此,如果您将 static 全局变量作为单个编译单元编译,甚至可以从其他文件访问它们。 This means that in reality, the scope of the global static variables is not the file but the compilation unit (which may or may not be one single file).这意味着实际上,全局 static 变量的 scope 不是文件,而是编译单元(可能是也可能不是单个文件)。

But, since you have a global static function, not a variable, it is accessible from everywhere as a global static function. But, since you have a global static function, not a variable, it is accessible from everywhere as a global static function.

EDIT: As suggested by @Peter Cordes in comments below, it may be a real mess with inline and static at the same time, so the official doc ( https://en.cppreference.com/w/cpp/language/inline ) says that the redefinition of inline functions (and variables since C++17) must be non-static.编辑:正如@Peter Cordes 在下面的评论中所建议的那样,它可能同时与 inline 和 static 混在一起,所以官方文档( https://en.cppreference.com/w/cpp/language/inline )表示内联函数(以及自 C++17 以来的变量)的重新定义必须是非静态的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM