堆栈内存是否在Linux中是连续的?

时间:2018-04-01 05:10:43

标签: linux heap-memory virtual-memory cpu-cache stack-size

据我所知,堆栈内存在虚拟内存地址中是连续的,但堆栈内存在物理上是连续的吗?这是否与堆栈大小限制有关?

编辑:

我曾经认为堆栈内存不必在物理上是连续的,但为什么我们认为堆栈内存总是比堆内存快?如果它不是物理上连续的,那么堆栈如何更好地利用缓存呢?还有另一件事总是让我感到困惑,cpu在数据段中执行指令,它不在虚拟内存中的堆栈段附近,我不认为操作系统会使堆栈段和数据段在物理上彼此接近,所以这可能会对缓存效果造成损害,您怎么看?

再次修改: 也许我应该举一个例子来更好地表达自己,如果我们想要对大量数字进行排序,使用数组来存储数字比使用列表更好,因为每个列表节点都可以由malloc构造,所以它可能不会很好地利用缓存,这就是为什么我说堆栈内存比堆内存更快。

4 个答案:

答案 0 :(得分:3)

  

据我所知,堆栈内存在虚拟内存中是连续的   地址,但堆栈内存也是连续的物理?这样做   与堆栈大小限制有关?

不,堆栈内存在物理地址空间中不一定是连续的。它与堆栈大小限制无关。它与操作系统如何管理内存有关。操作系统仅在第一次访问相应的虚拟页面时(或者自从它被分页到磁盘后第一次)分配物理页面。这称为demand-paging,它有助于节省内存使用量。

  

为什么我们认为堆栈内存总是更快   堆内存?如果它不是物理上连续的,那么如何堆叠   更多地利用缓存?

它与缓存无关。从堆中分配和释放内存的速度比堆快。这是因为从堆栈分配和取消分配只需要一条指令(递增或递减堆栈指针)。另一方面,从堆中分配和/或释放内存涉及更多工作。有关详细信息,请参阅this文章。

现在一旦分配了内存(从堆或堆栈),访问分配的内存区域所花费的时间取决于它是堆栈还是堆内存。这取决于内存访问行为以及它是否为friendly缓存和内存架构。

  

如果我们想要对大量数字进行排序,请使用数组来存储   数字比使用列表更好,因为每个列表节点都可以   由malloc构造,因此它可能无法充分利用缓存,   这就是为什么我说堆栈内存比堆内存快。

使用数组更快,不是因为数组是从堆栈中分配的。可以从任何内存(堆栈,堆或任何位置)分配数组。它更快,因为数组通常一次连续访问一个元素。访问第一个元素时,将包含元素和其他元素的整个缓存行从内存中提取到L1缓存。因此,访问该缓存行中的其他元素可以非常有效地完成,但访问缓存行中的第一个元素仍然很慢(除非缓存行为prefetched)。这是关键部分:由于缓存行是64字节对齐的,虚拟和物理页面也是64字节对齐,因此可以保证任何缓存行完全驻留在单个虚拟页面和单个物理页面中即可。这使得获取缓存行变得高效。同样,所有这些都与数组是从堆栈还是堆分配无关。无论哪种方式都适用。

另一方面,由于链表的元素通常不是连续的(甚至在虚拟地址空间中也不连续),因此包含元素的高速缓存行可能不包含任何其他元素。因此,获取每个元素可能会更加昂贵。

答案 1 :(得分:2)

不,没有承诺物理地址的连续性。但这没关系,因为用户空间程序不使用物理地址,所以不知道是这种情况。

答案 2 :(得分:2)

记忆是记忆。堆栈内存不比堆内存快,并且速度不慢。一切都是一样的。使内存成为堆栈或堆的唯一方法是应用程序如何分配内存。完全可以在堆上分配内存并使其成为程序堆栈。

速度差异在分配中。堆栈存储器通过从堆栈指针中减去一个指令来分配。

分配堆的过程取决于堆管理器,但它要复杂得多,并且可能需要将页面映射到地址空间。

答案 3 :(得分:1)

这是一个复杂的话题。

堆和堆栈(通常)具有相同的内存和内存类型(MTRR,每页缓存设置等)。 [mmap,文件,驱动程序可能有不同的策略,或者当用户明确更改它时]。

堆栈可能更快,因为它经常被使用。当您调用函数时,参数和局部变量将被放入堆栈,因此缓存是新鲜的。另外,因为函数经常调用和返回,所以可能在另一个缓存级别中有更多的堆栈,并且很少在堆栈的顶部被分页(因为它最近被使用)。

因此缓存可能会更快,但只要你的变量很少。如果允许堆栈上的大型数组,例如alloca,优势消失。

一般来说,这是一个非常复杂的主题,最好不要进行太多优化,因为它可能导致复杂的代码,因此更难以重构和高级代码优化。 (例如,在多维数组上,索引(以及存储器)和循环的顺序可以提高速度,但也很快就无法维护代码。)