在C中,当你编写这样的代码时:
void some_function(void) { while (something) { char buf[4096]; ... } }
在调用函数时是否会发生buf
的分配? 或者是否为循环的每次迭代都会进行单独的分配?
如果我把buf
的声明放在循环之外(即在函数的开头),会有任何性能提升吗?
buf在堆栈中some_function的框架中分配。 它只在调用some_function时分配一次。 所以即使你把buf的声明放在外面,你也不会获得任何性能提升。
但是,如果你写一些类似的东西,那就不一样了
while (...) { int a = 5; }
在循环。 赋值在每次迭代时发生。
实际上,缓冲区是在循环的每次迭代中分配的。 但是,编译器优化,并且在没有初始化器的情况下,它们实际上不会生成代码来执行任何操作以在每次迭代时分配空间; 就好像变量是在循环之外声明的那样。 在定义中添加初始化,您将看到对性能的影响,因为初始化将在循环的每次迭代中完成。
在通用处理器(x86,PowerPC,ARM)上的堆栈上分配最多是一条改变堆栈指针寄存器的指令。 这根本不会影响性能(见下面的注释)。 此外,编译器也可以为您提供循环外的堆栈分配。 底线是增益很小甚至没有。
注意:更改堆栈指针寄存器会在无序处理器中引入指令依赖性。
C标准允许编译器在每次迭代中分配和释放一次,或者为函数分配和释放一次。 在实践中,我见过的每个编译器都为该函数分配,而且还有很多。 然而,即使每次迭代分配一次,差异仍然是〜2指令使堆栈指针向下和向上碰撞(或向上和向下用于向上增长的堆栈)。 看到显着的性能差异将是罕见的。
在您的具体情况下,可能没有性能损失。 在最坏的情况下(没有任何优化),分配但是类似于:
sub sp, #4096
和解除分配是这样的
add sp, #4096
请记住,即使没有优化,对于循环中定义的所有局部变量,也可能只发生一次。 如果您有这样的事情:
它可能会被翻译成类似的东西
sub sp, #4100 . . . . add sp, #4100
这样做
void some_function(void) { char buf[4096]; while (something) { int x; ... } }
对于表现没有任何改变。
添加初始化:
void some_function(void) { while (something) { char buf[4096] = "Something" ; int x; ... } }
会增加性能。 在大多数情况下,开销很小。
但是,将对象放在打开Internet连接的循环中会大大减慢速度。
这是一个平衡问题。 对于大多数应用,
char buf[4096] = "Something" ;
不明显。 在处理实时中断的循环中,它可能是关键的。
代码清晰。 尽可能限制可变范围可提高清晰度。 表现来自表格设计; 没有编码。 如果您通过实际测量发现某些特定的编码结构导致运行缓慢,那么您可以更改代码。
以上就是c/c++开发分享循环内的堆栈分配相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/523262.html