在大型阵列上使用 VirtualAlloc 进行保留与提交+预留内存相比的好处



我正在编写一个C++程序,它基本上适用于非常大的数组。在Windows上,我使用VirtualAlloc为我的阵列分配内存。现在我完全理解了使用 VirutalAlloc 保留和提交内存之间的区别;但是,我想知道将内存逐页提交到保留区域是否有任何好处。特别是,MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85(.aspx( 包含MEM_COMMIT选项的以下说明:

除非/直到实际访问虚拟地址,否则不会分配实际的物理页。

我的实验证实了这一点:我可以保留并提交几GB的内存,而不会增加进程的内存使用量(如任务管理器所示(;实际内存仅在我实际访问内存时才分配。

现在我看到很多例子,认为应该保留大部分地址空间,然后逐页提交内存(或在某些更大的块中,取决于应用程序的逻辑(。然而,如上所述,内存似乎在访问它之前没有提交;因此,我想知道逐页提交内存是否有任何真正的好处。事实上,逐页提交内存实际上可能会减慢我的程序速度,因为许多系统调用实际提交内存。如果我一次提交整个区域,我只需支付一次系统调用的费用,但内核似乎足够智能,实际上只分配我实际使用的内存。

如果有人能向我解释哪种策略更好,我将不胜感激。

不同之处在于提交会针对页面文件"备份"内存。 举个例子:

  1. 给定 2GB 的物理 RAM 和 2GB 的交换(假设为此目的使用固定大小的交换(。
  2. 预留 6GB - 正常。
  3. 提交前 2GB - 确定。
  4. 提交剩余的 4GB - 失败。
  5. 将交换文件扩展到 8GB
  6. 提交剩余的 4GB - 成功。

使用 MEM_COMMIT 的原因主要是为了抑制运行时错误(应用稳定性(。 如果您有一个按需提交页面的进程,那么如果提交超过可用内存量 + 交换量,则始终有可能失败。当内存由页面文件支持时,您可以有力地保证内存从现在开始一直可用,直到您释放它为止。

这样或那样的原因有很多,我认为没有任何完美的科学来决定哪一种。 只有非常大的稀疏数组场景才需要单独MEM_RESERVE,例如:最多具有 25-33% 利用率的千兆字节数组(一种加速哈希表等的流行技术(。

几乎所有其他东西都是灰色地带,你可能会走任何一种方式 - MEM_COMMIT预先会让你自己的应用程序更稳定一些,并且基本上优先考虑物理RAM而不是可能按需分配的竞争应用程序。 (如果您先抓住 RAM,那么当物理内存耗尽时,您的应用程序将是最后一个站立的应用程序( 同时,如果您实际上没有使用所有这些 ram,那么您最终可能会限制客户端机器的多任务潜力,或者通过不断增长的页面文件造成不必要的磁盘空间浪费。

最新更新