据我所知,堆栈内存在虚拟内存地址中是连续的,但是堆栈内存在物理上也是连续的?这与堆栈大小限制有关吗?
编辑:
我曾经认为堆栈内存不必在物理上是连续的,但是为什么我们认为堆栈内存总是比堆内存快?如果它在物理上不是连续的,那么堆栈如何利用缓存的更多优势?还有另一件事总是让我感到困惑,cpu在数据段中执行指令,该指令不在虚拟内存中的堆栈段附近,我认为操作系统不会使堆栈段和数据段在物理上彼此靠近,因此这可能会损害缓存效果,您认为呢?
再次编辑: 也许我应该举一个例子来更好地表达自己,如果我们想对大量数字进行排序,使用数组存储数字要比使用列表更好,因为每个列表节点都可以由构造malloc,因此没有充分利用缓存,这就是为什么我说堆栈内存比堆内存快。
malloc
不,堆栈存储器在物理地址空间中不一定是连续的。它与堆栈大小限制无关。这与操作系统如何管理内存有关。仅当第一次访问相应的虚拟页面(或自从虚拟页面调出到磁盘以来的第一次)时,操作系统才分配物理页面。这称为需求分页,它有助于节省内存使用量。
为什么我们认为堆栈内存总是比堆内存快?如果它在物理上不是连续的,那么堆栈如何利用缓存的更多优势?
它与缓存无关。从堆栈分配和取消分配内存比堆快得多。这是因为从堆栈分配和取消分配仅需要一条指令(递增或递减堆栈指针)。另一方面,从堆分配和/或取消分配内存涉及许多工作。请参阅本文章以了解更多信息。
现在,一旦分配了内存(从堆或堆栈),访问分配的内存区域所花费的时间 就不 取决于它是堆栈还是堆内存。这取决于内存访问行为以及它是否对缓存和内存体系结构友好。
如果我们要对大量数字进行排序,那么使用数组存储数字要比使用列表更好,因为每个列表节点都可以由malloc构造,因此它可能无法充分利用缓存,这就是为什么我说堆栈内存比堆内存快。
使用数组更快,不是因为数组是从堆栈分配的。可以从任何内存(堆栈,堆或任何地方)分配数组。由于数组通常一次可连续访问一个元素,因此速度更快。当访问第一个元素时,包含该元素和其他元素的整个缓存行将从内存中提取到L1缓存中。因此,可以非常有效地访问该缓存行中的其他元素,但是访问缓存行中的第一个元素仍然很慢(除非预先提取了缓存行)。这是关键部分: 由于高速缓存行是64字节对齐的,并且虚拟和物理页面也都是64字节对齐的,因此可以确保任何高速缓存行完全驻留在单个虚拟页和单个物理页中 。这使得获取缓存行效率很高。同样,所有这些都与从堆栈还是堆分配数组无关。无论哪种方式,它都是正确的。
另一方面,由于链接列表的元素通常不连续(甚至不在虚拟地址空间中),因此包含元素的缓存行可能不包含任何其他元素。因此,获取每个元素可能会更昂贵。