Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 哪个更快:堆栈分配还是堆分配_C++_Performance_Memory_Stack_Heap - Fatal编程技术网

C++ 哪个更快:堆栈分配还是堆分配

C++ 哪个更快:堆栈分配还是堆分配,c++,performance,memory,stack,heap,C++,Performance,Memory,Stack,Heap,这个问题听起来可能相当简单,但这是我与另一位与我一起工作的开发人员进行的辩论 我在尽可能地将东西堆叠分配,而不是堆分配。他跟我说话,在我身后看着我,并评论说这是没有必要的,因为他们的表现是一样的 我一直认为,增加堆栈的时间是恒定的,堆分配的性能取决于当前堆在分配(找到适当大小的洞)和取消分配方面的复杂性(折叠孔以减少碎片,因为如果我没有弄错的话,许多标准库实现在删除过程中都会花费时间) 这对我来说可能是非常依赖于编译器的。尤其是对于这个项目,我使用的是架构编译器。了解这种组合将非常有帮助,但一般

这个问题听起来可能相当简单,但这是我与另一位与我一起工作的开发人员进行的辩论

我在尽可能地将东西堆叠分配,而不是堆分配。他跟我说话,在我身后看着我,并评论说这是没有必要的,因为他们的表现是一样的

我一直认为,增加堆栈的时间是恒定的,堆分配的性能取决于当前堆在分配(找到适当大小的洞)和取消分配方面的复杂性(折叠孔以减少碎片,因为如果我没有弄错的话,许多标准库实现在删除过程中都会花费时间)


这对我来说可能是非常依赖于编译器的。尤其是对于这个项目,我使用的是架构编译器。了解这种组合将非常有帮助,但一般来说,对于GCC和MSVC++,情况如何?堆分配的性能是否不如堆栈分配高?是否没有区别?或者差异如此微小,以至于变成了毫无意义的微观优化。

您可以为特定大小的对象编写一个性能非常好的特殊堆分配器。但是,通用堆分配器的性能并不特别好


另外,我同意Torbjörn Gylle的观点,这会带来对象的预期寿命。这一点很好!

您可以为特定大小的对象编写一个性能非常好的特殊堆分配器。但是,通用堆分配器的性能并不是特别好


我也同意Torbjörn Gylle的观点,这会带来对象的预期寿命。好的一点!

堆栈分配要快得多,因为它真正做的就是移动堆栈指针。 使用内存池,您可以从堆分配中获得相当的性能,但这会稍微增加复杂性并带来一些麻烦


此外,堆栈与堆不仅是性能方面的考虑因素;它还告诉您许多有关对象的预期生存期的信息。

堆栈分配要快得多,因为它真正做的就是移动堆栈指针。 使用内存池,您可以从堆分配中获得相当的性能,但这会稍微增加复杂性并带来一些麻烦


此外,堆栈与堆不仅是性能方面的考虑因素;它还告诉您许多有关对象的预期生存期的信息。

我认为堆栈分配和堆分配通常是不可交换的。我还希望这两种分配的性能足以供一般使用

我强烈建议使用较小的项目,无论哪个项目更适合分配范围。对于较大的项目,堆可能是必要的

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


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

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

我强烈建议使用较小的项目,无论哪个项目更适合分配范围。对于较大的项目,堆可能是必要的

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


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

堆栈速度更快。在大多数架构上,它实际上只使用一条指令,在大多数情况下,例如在x86上:

sub esp, 0x10
(将堆栈指针向下移动0x10字节,从而“分配”这些字节供变量使用。)

当然,堆栈的大小是非常非常有限的,因为如果您过度使用堆栈分配或尝试执行递归,您会很快发现:-)

此外,没有什么理由优化不需要验证的代码的性能,例如通过分析来演示。“过早优化”通常会导致更多的问题


我的经验法则是:如果我知道我在编译时需要一些数据,而数据的大小不到几百字节,我就堆栈分配它。否则我将堆分配它。

堆栈速度快得多。实际上,它在大多数体系结构上只使用一条指令,在大多数情况下,例如在x86上:

sub esp, 0x10
(将堆栈指针向下移动0x10字节,从而“分配”这些字节供变量使用。)

当然,堆栈的大小是非常非常有限的,因为如果您过度使用堆栈分配或尝试执行递归,您会很快发现:-)

此外,没有什么理由优化不需要验证的代码的性能,例如通过分析来演示。“过早优化”通常会导致更多的问题


我的经验法则是:如果我知道我在编译时需要一些数据,而数据的大小不到几百字节,我就堆栈分配它。否则我将堆分配它。

通常堆栈分配只是从堆栈指针寄存器中减去。这比搜索堆快很多

有时,堆栈分配需要添加一页或多页虚拟内存。添加一个新的零内存页并不需要从磁盘读取一个页,所以通常这仍然比搜索堆快很多(特别是
#include <cstdio>
#include <chrono>

namespace {
    void on_stack()
    {
        int i;
    }

    void on_heap()
    {
        int* i = new int;
        delete i;
    }
}

int main()
{
    auto begin = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000000; ++i)
        on_stack();
    auto end = std::chrono::system_clock::now();

    std::printf("on_stack took %f seconds\n", std::chrono::duration<double>(end - begin).count());

    begin = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000000; ++i)
        on_heap();
    end = std::chrono::system_clock::now();

    std::printf("on_heap took %f seconds\n", std::chrono::duration<double>(end - begin).count());
    return 0;
}
on_stack took 2.070003 seconds
on_heap took 57.980081 seconds
on_stack took 0.000000 seconds
on_heap took 51.608723 seconds
on_stack took 0.000003 seconds
on_heap took 0.000002 seconds
Proc P
{
  pointer x;
  Proc S
  {
    pointer y;
    y = allocate_some_data();
    x = y;
  }
}
  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:
class Foo {
public:
    Foo(int a) {

    }
}
int func() {
    int a1, a2;
    std::cin >> a1;
    std::cin >> a2;

    Foo f1(a1);
    __asm push a1;
    __asm lea ecx, [this];
    __asm call Foo::Foo(int);

    Foo* f2 = new Foo(a2);
    __asm push sizeof(Foo);
    __asm call operator new;//there's a lot instruction here(depends on system)
    __asm push a2;
    __asm call Foo::Foo(int);

    delete f2;
}