为什么malloc在超过一定阈值后依赖于mmap?

9

我在阅读关于malloc的一些内容,发现在malloc的手册页中有以下内容:

通常,malloc()从堆上分配内存,并根据需要使用sbrk(2)调整堆的大小。 当分配大于MMAP_THRESHOLD字节的内存块时,glibc malloc()实现将使用mmap(2)将内存分配为私有匿名映射。 MMAP_THRESHOLD默认情况下为128 kB,但可使用mallopt(3)进行调整。 使用mmap(2)执行的分配不受RLIMIT_DATA资源限制的影响(请参见getrlimit(2))。

因此,从MMAP_THRESHOLD开始,malloc开始使用mmap

  1. 有没有理由为大块内存切换到mmap
  2. 这会影响进程执行性能吗?
  3. mmap系统调用是否强制进行上下文切换?

1
(1) 是的; (2) 理论上是可以的,但在大多数情况下这会提高性能,这就是 (1) 的原因; (3) 每个系统调用都会这样。 - n. m.
@n.m. 并非所有的系统调用都需要进行上下文切换。请查看以下线程https://dev59.com/VGox5IYBdhLWcg3wYzbX - rkachach
显然这是术语上的差异。你可能想知道mmap是否是阻塞的。调用本身可能不会阻塞,但这并不重要。你的进程将会遇到页面错误并被迫进行上下文切换。 - n. m.
1个回答

15

(1) 通过匿名获取的页面可以通过< munmap >释放,这也是glibc所做的。所以对于小内存分配,会将内存返回到进程的堆中(但仍保留在进程的内存中);对于大内存分配,会将内存返回给整个系统。

(2) 通过匿名获取的页面直到您第一次访问它们时才实际分配。此时,内核必须将它们清零以避免在进程之间泄漏信息。因此,是的,由获取的页面第一次访问时比通过您进程的堆回收的页面慢。您是否会注意到差异取决于您的应用程序。

不使用的成本是,释放的内存仍然被您的进程占用,并且其他系统进程无法使用该内存。因此,这最终是一种权衡。

(3) 它不会强制进行上下文切换,我认为也不太可能引起上下文切换。 实际上并没有分配页面;它只是操作您进程的页面映射。这通常应该是一个非阻塞操作。(虽然我承认我不100%确定。)


谢谢你的回答。我仍在调查第三点,只是想看看mmap是否会强制进行上下文切换。 - rkachach
@rkachach,您有关于这个问题的任何更新吗?我也在尝试了解mmap系统调用是否会导致上下文切换。 - talekeDskobeDa
@talekeDskobeDa 不能保证它会发生,也不能保证它不会发生。你不能依赖任何一种行为。 - zwol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接