2017-11-25 154 views
4

我在这件事上听到了矛盾的意见。有些人说,访问堆中分配的数据(即std::vector或通过malloc分配的动态数组)总是比访问堆栈中分配的数据稍微慢一些,因为进程必须始终通过中间指针访问该数据,这可能位于完全不同的记忆区域;另一方面,他们维护,访问堆栈中分配的数据不需要通过这个中间指针,这些数据可能已经被缓存了。在堆上分配的数据比在堆栈上分配的数据要慢吗?

其他人声称,堆上的数据分配比堆栈上的要慢(由于malloc,mmap和类似函数的开销),但访问不是,除了堆栈和堆的罕见情况位于不同的物理驱动器上。

是什么事实?

+1

没有道理。这取决于您的整个系统 - 代码和硬件。在[NUMA机器]上更为复杂(https://en.wikipedia.org/wiki/Non-uniform_memory_access)。如果您确实需要知道,请分析您的应用程序并进行测试。 –

+3

错误,堆栈和堆都不与物理驱动器相关联。 –

+0

当内存访问转到'swap'(通常在物理驱动器上)时,您的代码不再是'快速',既不堆栈也不堆栈。 –

回答

2

事实上(至少在最现代的cpus上)是堆栈和堆执行相同的操作,因为它们都只是RAM的一部分。所以解引用指针几乎是一样的。

不同之处在于堆栈是为您的进程/线程预分配的,因此您不需要使用mallocfree系统调用即可使用它。特别是malloc是昂贵的。另一个区别是可能有一些特定的CPU指令用于使用堆栈来提高性能(例如程序集的push,pop)。然而,这些不太可能与内存访问有关(如将内存加载到寄存器)本身。

另一个区别是,如果你用完堆栈,你的程序将会(更可能)崩溃。虽然如果你用完堆,那么你的操作系统可能会使用交换为你降低性能成千上万次。

缓存未命中当然是一个因素,它会更经常发生在堆上,然后在堆栈上。但是,这只是因为与堆栈相比堆很大。但请注意,除非您编写的代码非常繁重,否则缓存未命中并不重要。

现在你是对的std::vector必须解除引用附加时间。但是这里缓慢的是解引用,而不是堆栈或堆中的指针。它们在哪里并不重要。双引号总是比单引号慢。

现在栈和堆也可​​能位于不同的物理设备上。而且这两款设备的速度不同(可能会使堆速更快)。但是这又与堆栈和堆本身无关。这可能发生在内存的任何两个部分。而且你无法对此做任何事情。甚至没有操作系统可以(可能,也可以,我不确定)。这是主板的事情。无论如何,主板很可能会为更快的设备降频。

0

有人说,在堆上分配访问数据(即标准::载体或通过分配的malloc动态数组)总是略高于访问堆栈上分配的数据速度较慢,因为该过程必须总是通过一个中间指针访问那些可能位于完全不同的记忆区域的数据;另一方面,他们维护,访问堆栈中分配的数据不需要通过这个中间指针,这些数据可能已经被缓存了。

这是牛粪便废物。没有中间指针寄存器,只能访问静态。通过寄存器(SP)访问堆栈数据,其中一些处理器具有补充堆栈寄存器(例如,BP,AP)。

另外,内存是内存是内存。唯一认为使内存成为堆栈的是它作为堆栈被访问。

其他声称数据的唯一分配在堆上比堆(因为malloc的,MMAP和类似功能的开销)上慢,但访问不是

这是正确的。在堆栈上分配数据只需要一条指令。