函数局部静态变量:从性能角度看的优缺点
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 的内存量。我在答案中添加了注释。以上是关于函数局部静态变量:从性能角度看的优缺点的主要内容,如果未能解决你的问题,请参考以下文章