我正在分配2个相同大小的数组,一个在堆栈上,一个在堆上,然后通过简单的赋值迭代它们。
编译Executable为主线程堆栈分配40mb。
此代码仅在vc ++中使用/ STACK:41943040链接器标记进行了测试。
#include "stdafx.h"
#include <string>
#include <iostream>
#include <malloc.h>
#include <windows.h>
#include <ctime>
using namespace std;
size_t stackavail()
{
static unsigned StackPtr; // top of stack ptr
__asm mov [StackPtr],esp // mov pointer to top of stack
static MEMORY_BASIC_INFORMATION mbi; // page range
VirtualQuery((PVOID)StackPtr,&mbi,sizeof(mbi)); // get range
return StackPtr-(unsigned)mbi.AllocationBase; // subtract from top (stack grows downward on win)
}
int _tmain(int argc, _TCHAR* argv[])
{
string input;
cout << "Allocating 22mb on stack." << endl;
unsigned int start = clock();
char eathalfastack[23068672]; // approx 22mb
auto length = sizeof(eathalfastack)/sizeof(char);
cout << "Time taken in ms: " << clock()-start << endl;
cout << "Setting through array." << endl;
start = clock();
for( int i = 0; i < length; i++ ){
eathalfastack[i] = i;
}
cout << "Time taken in ms: " << clock()-start << endl;
cout << "Free stack space: " << stackavail() << endl;
cout << "Allocating 22mb on heap." << endl;
start = clock();
// auto* heaparr = new int[23068672]; // corrected
auto* heaparr = new byte[23068672];
cout << "Time taken in ms: " << clock()-start << endl;
start = clock();
cout << "Setting through array." << endl;
for( int i = 0; i < length; i++ ){
heaparr[i] = i;
}
cout << "Time taken in ms: " << clock()-start << endl;
delete[] heaparr;
getline(cin, input);
}
输出是这样的:
Allocating 22mb on stack.
Time taken in ms: 0
Setting through array.
Time taken in ms: 45
Free stack space: 18872076
Allocating 22mb on heap.
Time taken in ms: 20
Setting through array.
Time taken in ms: 35
为什么堆栈数组的迭代速度比堆上的相同?
编辑: nneonneo cought我的错误
现在输出相同:
Allocating 22mb on stack.
Time taken in ms: 0
Setting through array.
Time taken in ms: 42
Free stack space: 18871952
Allocating 22mb on heap.
Time taken in ms: 4
Setting through array.
Time taken in ms: 41
根据ÖöTiib的回答发布版本:
Allocating 22mb on stack.
Time taken in ms: 0
Setting through array.
Time taken in ms: 5
Free stack space: 18873508
Allocating 22mb on heap.
Time taken in ms: 0
Setting through array.
Time taken in ms: 10
答案 0 :(得分:9)
你的阵列大小不一样; sizeof(char[23068672]) != sizeof(int[23068672])
,元素属于不同类型。
答案 1 :(得分:1)
你的电脑出了问题,在我的Pentium 4老电脑上需要15毫秒来分配这种基于堆栈的字符串。您是否尝试使用调试版本?
答案 2 :(得分:0)
您的问题分为两部分:
分配空间
首先,让我们看看在堆栈上分配空间。我们知道的堆栈在x86架构上向下发展。因此,为了在堆栈上分配空间,您所要做的就是减少堆栈指针。只有一个汇编指令(dec sp,#amount)。该汇编指令始终存在于函数的序言中(函数设置代码)。所以,据我所知,在堆栈上分配空间不能占用任何时间。在堆栈上分配空间的成本=(递减sp操作)。在现代超标量机器上,此指令的执行将与其他指令重叠。
另一方面,在堆上分配空间需要对new / malloc进行库调用。库调用首先检查堆上是否有一些空间。如果是,则它将返回指向第一个可用地址的指针。如果堆栈上没有空间,它将使用brk系统调用来请求内核修改其他页面的页表条目。系统调用是一项代价高昂的操作。它会导致管道冲洗,TLB污染等。因此,在堆上分配空间的成本=(函数调用+空间计算+(brk系统调用)?)。当然,在堆上分配空间似乎比堆栈慢一个数量级。
访问元素 x86 ISA的寻址模式允许使用直接寻址模式(temp = mem [addr])寻址存储器操作数以访问全局变量,而堆栈上的变量通常使用索引寻址模式进行访问。 (温度= MEM [堆栈指针+偏移堆栈上])。我的假设是两个存储器操作数应该几乎相同的时间,但直接寻址模式似乎肯定比索引寻址模式更快。关于数组的内存访问,我们有两个操作数来访问任何元素 - 数组的基地址和索引变量。当我们在堆栈上访问数组时,我们再添加一个操作数 - 堆栈 - 指针。 x86寻址模式提供了这样的地址 - base + scale * index + offset。所以,好的堆栈数组元素访问:temp = mem [sp + base-address + iterator * element-size]和堆数组访问:temp = mem [base-address + iterator * element-size]。显然,堆栈访问必须比数组访问更昂贵。
现在,进入迭代的一般情况,如果堆栈的迭代速度较慢,则意味着寻址模式 可能 (我不完全确定)瓶子 - 如果分配空间是瓶颈,系统调用可能是瓶颈。