2014-12-04 80 views
1

我刚刚经历了一堆堆叠VS堆在这里的线程堆栈溢出的去(和其他随机网站通过谷歌找到),但我无法找到提供太多的答案(如果有的话)对读/写速度问题的深度(大多数答案和文章侧重于分配速度)。堆VS堆栈关于读取/写入速度

如果我正在写一个C程序(在我的例子中是一个游戏),我将对象数据存储在一个几KB的缓冲区中,如果它存在差异(就访问速度而言)if该缓冲区是分配在堆栈上还是堆上?或者,当决定硬件(即高速缓存或RAM)的存储位置时,编译器是否会以相同的方式处理该大小的缓冲区?

+0

访问RAM本质上是独立的地址,并在你的进程的虚拟地址映射到一个随机的,不可知的物理地址呢。比内存的特定位置更重要的是内存访问模式中的缓存行为。 (还有一个分配本身的同步成本,但你没有问那个问题。) – 2014-12-04 10:52:08

+0

“内存访问模式”是指将对象数据存储为数组的结构而不是结构数组(XXXYYYZZZ vs XYZXYZXYZ)? (编辑:啊没关系我是个白痴,只是看着它 - 你的意思是我的程序访问数据的方式......对吧?) – DudeMan2000 2014-12-04 11:03:47

+0

@ DudeMan2000数组和结构数组的结构不是一回事:)但是,是的,KerrekSB意味着你抬起头来。如果你有一个1GB的字节数组,如果你从头到尾循环访问整个GB,或者访问次序是随机的,或者你访问的是相同KB的1000000次,那么这很重要。 – deviantfan 2014-12-04 11:13:14

回答

4

在一个典型的现代CPU和OS,不,我不希望在平均访问时间任何区别,高速缓存未命中,或者(更糟糕)的基础上的缓冲区是堆或栈页面错误的可能性的可能性。与其他内存使用相比,唯一重要的是访问它的模式。但是,可能存在嵌入式或专用平台,其中堆栈保存在与堆不同的内存中。

您忽略了第三种可能性,即非堆内存(由某些OS特定的调用分配,如mmap而不是malloc)。

最后,如果你想彻底删除页面错误的可能性,操作系统可以提供一种方式来做到这一点;例如,POSIX上的mlock

+0

您可能想要添加一些关于访问它的不同方法,例如通过指针,使用代码相对地址(PIC)作为来自堆栈指针的偏移量......这些可能对寄存器有不同的影响 - 压力和访问开销,他们可能会使用不同的指令(或指令序列)。 – Deduplicator 2014-12-04 11:15:43

+0

不错,谢谢!我没有听说过mmap,也没有读过关于页面错误的文章,我会更多地关注这些。 – DudeMan2000 2014-12-04 11:15:55

2

访问速度没有区别,毕竟它的内存相同。编译器决不会决定缓冲区应存储在哪里物理上。这是硬件和操作系统业务。

+0

真的吗?我认为编译器会进行优化,如果您创建了一个局部变量并且该变量在释放之前被使用了很多,那么编译器会将该变量分配给一个寄存器。编译器是否仅使用寄存器进行调用,而所有非寄存器内存被编译器视为“虚拟内存”,并由操作系统和硬件管理? – DudeMan2000 2014-12-04 10:59:42

+0

@ DudeMan2000是的,编译器可以做到这一点。但问题是关于缓冲区,而不是变量。编译器不能满足:“嗯。这是非常重要的缓冲区让我们把它放到处理器的二级缓存“ – Ari0nhh 2014-12-04 11:01:46

+0

@ DudeMan2000简化:几乎所有的东西都必须从RAM加载到寄存器,当在处理器中使用,然后改变的值(如果有的话)必须是处理器的寄存器数量有限(不是所有必需的都适合),但是在RAM和寄存器之间的加载和存储需要时间,编译器可以做的是保留一块最常用的变量的代码在一段时间内没有加载/卸载,但是这与RAM中的位置无关 – deviantfan 2014-12-04 11:05:53

2

根本没有。 heap ad stack是操作系统向您的应用程序提供的虚拟地址空间中的区域。它们的区别在于你的应用程序在stack中存储的内容以及heap中的内容。所有参考类型都存储在heap中,所有值类型都存储在stack中。此外,存储在stack中的事物的生命周期与应用的生命周期持续时间相同,而存储在heap中的类型可能会被垃圾回收,并且他们正在使用的内存将被回收。