这个问题可能听起来相当简单,但这是我与另一位开发人员的争论。

我小心地在我可以的地方进行堆栈分配,而不是堆分配。他和我说话,看着我的肩膀,并评论说,这是没有必要的,因为他们的表现是一样的。

在我的印象中,增加堆栈是一个常数时间,而堆分配的性能取决于当前堆的复杂性,包括分配(找到合适大小的孔)和反分配(缩小孔以减少碎片,如果我没有弄错的话,许多标准库实现在删除过程中需要时间来做这件事)。

在我看来,这可能非常依赖于编译器。在这个项目中,我特别使用了一个用于PPC架构的Metrowerks编译器。对这种组合的深入了解将是最有帮助的,但一般来说,对于GCC和msvc++,情况如何?堆分配不如堆栈分配高效吗?没有区别吗?还是差异如此之小以至于变成了毫无意义的微观优化。


当前回答

不要做过早的假设,因为其他应用程序代码和使用可能会影响您的功能。因此,孤立地看待函数是没有用的。

如果你是认真的应用程序,那么VTune它或使用任何类似的分析工具,并查看热点。

糯米

其他回答

我想说的是,实际上GCC生成的代码(我还记得VS)不需要做堆栈分配的开销。

对以下函数表示:

  int f(int i)
  {
      if (i > 0)
      {   
          int array[1000];
      }   
  }

下面是生成的代码:

  __Z1fi:
  Leh_func_begin1:
      pushq   %rbp
  Ltmp0:
      movq    %rsp, %rbp
  Ltmp1:
      subq    $**3880**, %rsp <--- here we have the array allocated, even the if doesn't excited.
  Ltmp2:
      movl    %edi, -4(%rbp)
      movl    -8(%rbp), %eax
      addq    $3880, %rsp
      popq    %rbp
      ret 
  Leh_func_end1:

所以无论你有多少局部变量(甚至在if或switch内部),只有3880会改变为另一个值。除非你没有局部变量,否则这条指令只需要执行。所以分配局部变量没有开销。

一般来说,正如上面几乎每个答案所提到的,堆栈分配比堆分配快。堆栈的push或pop是O(1),而从堆中分配或释放可能需要遍历之前的分配。但是,您通常不应该在紧凑的性能密集型循环中进行分配,因此选择通常取决于其他因素。

做出这样的区分可能会有好处:您可以在堆上使用“堆栈分配器”。严格地说,我认为堆栈分配是指分配的实际方法,而不是分配的位置。如果你在实际的程序堆栈上分配了很多东西,这可能会因为各种各样的原因而变得很糟糕。另一方面,在可能的情况下使用堆栈方法在堆上进行分配是分配方法的最佳选择。

既然你提到了《Metrowerks》和《PPC》,我猜你指的是Wii。在这种情况下,内存是非常宝贵的,在任何可能的情况下使用堆栈分配方法都可以保证您不会在片段上浪费内存。当然,这样做需要比“普通”堆分配方法更加小心。对每种情况进行权衡是明智的。

我不认为堆栈分配和堆分配通常是可以互换的。我也希望它们的性能都足以用于一般用途。

我强烈推荐小件物品,哪种更适合分配范围。对于较大的项,堆可能是必要的。

在有多个线程的32位操作系统上,堆栈通常是相当有限的(尽管通常至少是几mb),因为需要分割地址空间,迟早一个线程堆栈会碰到另一个线程堆栈。在单线程系统(至少是Linux glibc单线程)上,限制要小得多,因为堆栈可以不断增长。

在64位操作系统上,有足够的地址空间使线程堆栈相当大。

通常,堆栈分配只是由堆栈指针寄存器中的减法组成。这比搜索堆快多了。

Sometimes stack allocation requires adding a page(s) of virtual memory. Adding a new page of zeroed memory doesn't require reading a page from disk, so usually this is still going to be tons faster than searching a heap (especially if part of the heap was paged out too). In a rare situation, and you could construct such an example, enough space just happens to be available in part of the heap which is already in RAM, but allocating a new page for the stack has to wait for some other page to get written out to disk. In that rare situation, the heap is faster.

这不仅仅是堆栈分配更快。您还可以在使用堆栈变量方面获得很多好处。它们有更好的参考位置。最后,折价也便宜得多。