堆栈中的循环内分配(Stack allocation inside a loop)

2019-10-21 04:19发布

在C语言中,当你写这样的代码:

void some_function(void) {
    while (something) {
        char buf[4096];
        ...
    }
}

是否分配buf当函数被调用发生的呢? 抑或是一个独立的分配发生了循环的每次迭代?

会不会有,如果我把声明的任何性能增益buf环路(即在函数的开头)之外吗?

Answer 1:

的BUF在some_function的堆栈上的帧中分配。 它只有当some_function被称为被分配一次。 所以,即使你把BUF的声明之外,你不会得到任何性能增益。

但它是不同的,如果你喜欢写东西

while (...) {
  int a = 5;
}

在循环。 分配情况每次迭代。



Answer 2:

实际上,缓冲器被分配在循环的每次迭代。 编译器优化,虽然,那里是没有初始化,他们实际上不会产生代码,做任何事情来分配每个迭代的空间; 它会像如果变量外循环声明。 添加初始化的定义,你会看到对性能有影响的初始化将在循环的每个迭代来完成。



Answer 3:

分配在通用处理器的堆栈上(X86,PowerPC的,ARM)是至多单个指令改变堆栈指针寄存器。 这不会影响性能太多可言(见下面的注释)。 此外,编译器可以扯起堆栈分配的循环之外的你。 底线是,增益是小到没有。

注意:改变堆栈指针寄存器可以引入在乱序处理器指令的依赖关系。



Answer 4:

C标准允许编译器对函数分配和释放在每次迭代或一次。 在实践中,每一个我见过的编译器分配的功能,这是相当多的。 即使分配每次迭代曾经,然而,差别是〜2个指令凸点栈指针向下和向上(或上下用于向上生长栈)。 眼看显著的性能差异将是罕见的。



Answer 5:

在您的具体情况,有可能是没有性能损失。 在最坏的情况下(无任何优化),分配却是一样的东西:

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

将增加对性能的影响。 在大多数情况下,开销会很小。

然而,把一个物体在打开互联网连接将大大慢下来一环。

这是一个平衡的问题。 对于大多数应用,

      char buf[4096] = "Something" ;

并不明显。 在循环递过实时中断,这可能是至关重要的。

代码清晰。 具有可变范围尽可能限制提高清晰度。 性能配备形式设计; 无需编码。 如果通过某些特定的编码结构是造成东西运行缓慢实际测量发现,那么你可以更改代码。



文章来源: Stack allocation inside a loop