函数局部静态变量:从性能角度看的优缺点

Posted

技术标签:

【中文标题】函数局部静态变量:从性能角度看的优缺点【英文标题】:Function local static variables: pros/cons from performance point of view 【发布时间】:2019-12-16 16:49:35 【问题描述】:

函数局部静态变量纯粹从性能的角度来看有哪些优点/缺点?

这是一个例子:

// version 1
void func(/*some arguments here*/)

 int64_t x;
 int32_t y = 0;
 void * p = 0;
 // do something here


// version 2
void func(/*some arguments here*/)

 static int64_t x;
 static int32_t y; y = 0;
 static void * p; p = 0;
 // do something here

哪个版本会更快?它会永远更快吗?在什么情况下,使用静态局部变量来提高性能可能会打自己的脚?

非常感谢您的帮助!

【问题讨论】:

哪个版本会更快? -- 请测量。其次,从 C++ 11 开始,静态变量需要进行线程安全初始化,而局部变量始终是线程安全的。因此,static 很可能会影响性能。 相关/欺骗:***.com/questions/21488559/… @PaulMcKenzie,谢谢!因此,答案是“视情况而定,但性能很可能会受到影响”。 避免函数局部静态变量的一个非常重要的原因是,如果您写入它们会使函数非线程安全,除非您自己显式添加同步,这甚至会增加更多的性能损失。您可以使用thread_local,但这仍然会受到打击。除非问题特别需要,否则避免使用它们。 规则可能有一个例外: 1. 您肯定处于单线程环境中,永远不会获得多线程。 2. 构造有问题的对象很昂贵(可能涉及分配大块内存),但简单地重置对象很便宜。但是如果你违背了单线程的承诺,你就会有麻烦了!因此,如果您在 profiling(!) 之后发现您在此位置确实存在真正的瓶颈,这可能是一个考虑因素,其他任何事情都将是过早的优化。 【参考方案1】:

这个问题太宽泛了,一般无法回答。但是,我只想分享一些实际应用程序开发的经验。正如 @Aconcagua 在 cmets 中所指出的,如果辅助(未返回)本地对象的初始化或使用成本很高,则将其设为 static 并重用它可能会显着加快速度。这发生在我们的案例中,尤其是辅助局部向量,其中重用避免了堆分配。比较

void f() 
  std::vector<...> v;
  ...  // at least one allocation required in each call when inserting elements

void f() 
  static std::vector<...> v;
  v.clear();
  ...  // no allocation required if elements fit into capacity

这同样适用于(非小)字符串。当然,如果可以通过这种方式创建非常大的向量/字符串,则应该注意这种方法可能会显着增加进程 RSS(映射到 RAM 的内存量)。

在多线程应用程序中,我们只使用thread_local 而不是static


另一方面,对于基本类型的小对象(例如示例代码中的整数或指针),我敢说将它们设为static 可能会导致更多的内存访问。对于非静态变量,它们更有可能只映射到寄存器。对于静态变量,它们的值必须在函数调用之间保留,这很可能导致它们存储在内存中

【讨论】:

什么是“程序 RSS”? @KonradRudolph 将 program 更改为 process 好的,什么是“处理 RSS”?除非您专门在操作系统附近工作,否则这不是一个常见的缩写。 @KonradRudolph 抱歉,您以为您指的是 program 的错误用法。 驻留集大小 — 映射到 RAM 的内存量。我在答案中添加了注释。

以上是关于函数局部静态变量:从性能角度看的优缺点的主要内容,如果未能解决你的问题,请参考以下文章

C++中的全局变量普通局部变量和静态局部变量的区别

staticautoregisterextern

js全局变量优点和缺点

C++0x 和静态局部变量的性能损失?

lua脚本有静态局部变量吗

2017-7-3