为什么分配堆内存比分配堆栈内存快得多?

时间:2019-07-30 14:19:00

标签: c++ performance heap-memory stack-memory

我尝试为堆和堆栈内存中的10 ^ 7个整数分配空间,以查看哪个更快。显然,在堆内存中分配要快得多,但我不明白原因。

#include <bits/stdc++.h>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();

  int *p = new int[1e7];

  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  auto duration = duration_cast<microseconds>( t2 - t1 ).count();
  cout << duration / 1e6 << "\n"; // 5e-06



  t1 = high_resolution_clock::now();

  vector<int> v(1e7);

  t2 = high_resolution_clock::now();
  duration = duration_cast<microseconds>( t2 - t1 ).count();
  cout << duration / 1e6 << "\n"; // 0.112284

  return 0;
}

4 个答案:

答案 0 :(得分:15)

* def users = function(i){ return karate.call("classpath:v1/createCustomer.feature", { "firstName": '#(firstName)', "lastName": '#(lastName)' }) * def usersResult = karate.repeat(2, users ) * match each usersResult[*].responseStatus == 204 为1e7 new int[1e7]个值分配空间,并且不初始化它们。

int在堆栈上创建一个vector<int> v(1e7);对象,该对象的构造函数为堆上的1e7 vector<int>值分配空间。 将每个int值初始化为0。

速度上的差异是由于初始化。

要比较堆栈分配的速度,您需要在堆栈上分配一个数组:

int

但要警告:这很有可能会失败,因为堆栈不足以容纳那么大的数组。

答案 1 :(得分:7)

我只是一个初学者,但请允许我给出主要了解自己的知识。

vector<int> v(1e7);

您要在堆上为1000万个整数分配连续的内存。

vector<int>

您正在堆栈存储器中分配一个int[1e7]对象。在该对象的成员之间,有一个指向堆上的int()的指针,该指针也已分配。此外,其中的所有值都使用{{1}}的值(带有0s)进行初始化。参见constructor (2) of std::vector

答案 2 :(得分:5)

其他答案指出,向量构造函数中至少有一个“隐藏”初始化。

但是您的示例还有另一个问题:也许它甚至无法衡量您的想法。在C ++中对未优化的代码进行基准测试几乎是没有意义的,正确地对优化的代码进行计时也很困难。

让我们看一下您的(为便于阅读而修改)的示例,它由Clang编译,优化级别为-O3godbolt link

double test1() {
  high_resolution_clock::time_point t1 = high_resolution_clock::now();

  int *p = new int[1e7];

  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  auto duration = duration_cast<microseconds>( t2 - t1 ).count();
  return duration / 1e6; // 5e-06
}

编译为:

test1():                              # @test1()
        push    rbx
        call    std::chrono::_V2::system_clock::now()
        mov     rbx, rax
        call    std::chrono::_V2::system_clock::now()
        sub     rax, rbx
        movabs  rcx, 2361183241434822607
        imul    rcx
        mov     rax, rdx
        shr     rax, 63
        sar     rdx, 7
        add     rdx, rax
        cvtsi2sd        xmm0, rdx
        divsd   xmm0, qword ptr [rip + .LCPI0_0]
        pop     rbx
        ret
.LCPI1_0:
        .quad   4696837146684686336     # double 1.0E+6

第一部分甚至没有将运算符称为new!编译器浏览了您的程序,并意识到您从未使用分配的数组,因此它从生成的可执行文件中删除了分配。

因此,使用此类设置进行编译会使测量变得毫无意义时,程序的第一部分根本不会在堆上分配数组。

我建议阅读基准测试,并使用专门的微基准测试框架进行此类测试。看看Google Benchmark(和在线QuickBench)及其文档。

答案 3 :(得分:0)

我想指出,堆栈分配在运行时绝对不需要时间;所有工作都由编译器完成。 无论优化如何,比较都是毫无意义的。