【问题标题】:What happens to allocated pages that are mostly empty?大部分为空的已分配页面会发生什么?
【发布时间】:2018-08-05 02:01:09
【问题描述】:

如果一个进程最初在堆中分配了许多页面,但页面中的许多数据已被释放,操作系统是否会进行某种优化以将数据合并到一个页面中,所以可以释放其他页面吗?

【问题讨论】:

标签: linux unix operating-system


【解决方案1】:

一般来说,什么都不会发生,堆中会继续有“洞”。

由于进程已知的(虚拟)内存地址必须保持有效,操作系统不能自行执行“堆压缩”。但是,像 .Net 这样的一些运行时会这样做。

如果您使用的是 C 或 C++,默认情况下您只能希望 malloc() 能够重用以前释放的块。但是如果你的使用模式是“分配很多小对象,然后随机释放其中的一半”,那么内存利用率可能不会从峰值下降太多。

【讨论】:

  • 操作系统甚至可以知道分配的页面有多少正在使用吗?
  • @TonyTannous:一般来说不太可能。
  • 堆没有漏洞。它是一个连续的虚拟内存范围(或多个,在允许分配更多数据段的系统中,使用mmap(2) 系统调用),但它没有漏洞。
  • @LuisColorado 堆随机化使其不连续。
  • @TonyTannous,你有堆随机化的参考吗?它的目的是什么?
【解决方案2】:

如果一个进程最初在堆中分配了许多页

进程最初不会在堆中分配页面。

操作系统是否进行了某种优化以将数据整合到一个页面中,以便可以释放其他页面

操作系统不知道用户堆。它将页面分配给进程。该进程对这些页面的处理取决于它(即,将它们用于堆、堆栈、代码等)。

进程的堆管理器可以合并已释放的内存块。发生这种情况时,通常是为了对抗堆碎片。但是,我从未见过在页面被操作系统映射后取消映射页面的分页系统上的堆管理器。

【讨论】:

    【解决方案3】:

    进程堆上永远不会有漏洞。堆是分配给进程的数据段的一部分,它动态地向上增长到堆栈段的顶部,基本上使用sbrk(2) 系统调用(将新的大小固定到数据段)所以堆是分配页面的连续段(至少在虚拟地址空间方面)。 malloc(3) 永远不会将堆空间(或其中的一部分)返回给系统。有关此信息,请参阅malloc(3)。虽然有些内存分配器允许一个进程拥有多个堆(通过分配新的内存段,通过使用mmap(2) 系统调用),但由内存分配器分配的段通常永远不会返回给系统。

    发生的情况是内存分配器重用sbrk(2)mmap(2)分配的堆空间并管理内存以供重用,但它永远不会返回给系统。

    但不要害怕,因为无论如何,这都是由系统以一种良好且有利可图的方式处理的。

    这应该不会影响整个系统管理,除了它会消耗虚拟地址空间,并且如果您不使用它们,页面内容可能会在交换设备中结束,直到进程再次引用它们并使系统从交换设备重新加载它们。如果您的进程不重用它在堆中创建的空洞,那么系统最可能的目的地是将它们移动到交换设备并继续将其重用于其他进程。

    目前,我不知道系统是否通过不换出零页来优化交换分配,例如,对于可执行文件的文本段(它们从不去交换设备,因为它们的内容是已在可执行文件中交换 ---这是您无法在古代 unices 中擦除程序可执行文件的原因,或者不再需要在常用程序中使用粘性位的原因 - --) 但我认为不会(原因是应用程序最不可能将未使用的页面归零)

    只有在您的系统中有 15Gb 单进程的堆使用并且 90% 的堆使用大部分时间都没有使用的情况下才会被警告。但是在优化分配资源方面要考虑得更好,因为消耗 15Gb 堆而大多数时间 90%+ 未使用的进程似乎是一个糟糕的设计。如果您没有其他机会,只需为您的系统提供足够的交换空间即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多