我正在编写一个C ++程序,它基本上适用于非常大的数组。在Windows上,我使用VirtualAlloc为我的阵列分配内存。现在我完全理解使用VirutalAlloc保留和提交内存之间的区别;但是,我想知道将内存逐页提交到保留区域是否有任何好处。特别是,MSDN(http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx)包含对MEM_COMMIT选项的以下说明:
除非实际访问虚拟地址,否则不会分配实际物理页面。
我的实验证实了这一点:我可以保留并提交几GB的内存,而不会增加我的进程的内存使用量(如任务管理器中所示);实际内存只有在我实际访问内存时才会被分配。
现在我看到了很多例子,他们认为应该保留大部分地址空间,然后逐页提交内存(或者在一些更大的块中,具体取决于应用程序的逻辑)。但是,如上所述,在访问内存之前,似乎没有提交内存;因此,我想知道在逐页提交内存方面是否有任何实际好处。实际上,由于许多系统调用实际存储内存,逐页提交内存实际上可能会减慢我的程序速度。如果我一次提交整个区域,我只支付一个系统调用,但内核似乎足够智能,实际上只分配我实际使用的内存。
如果有人能向我解释哪种策略更好,我将不胜感激。
答案 0 :(得分:2)
不同之处在于提交内存与页面文件“后退”。举个例子:
使用MEM_COMMIT的原因主要是运行时错误抑制(应用程序稳定性)。如果您有一个按需提交页面的进程,那么如果超出内存量+可用交换量,那么沿途提交总是有可能失败。当页面文件支持内存时,您就有强保证内存可以从现在开始使用,直到您释放内存为止。
有很多理由可以采用这种方式,我认为没有任何完美的科学来决定哪种方式。对于非常大的稀疏数组场景,MEM_RESERVE本身仅需要,例如:多千兆字节阵列,利用率最高为25-33%(一种加速哈希表的流行技术等)。
几乎所有其他东西都是灰色区域,你可以选择其中任何一种方式 - MEM_COMMIT前置会使你自己的应用程序更加稳定,并且基本上优先考虑物理内存,而不是可能按需分配的竞争应用程序。 (如果你先抓住ram然后你的应用程序将是物理内存耗尽时的最后一个站点)同时,如果你实际上没有使用所有那些ram那么你可能最终限制你的多任务潜力客户端的机器或通过不断增长的页面文件导致不必要的浪费磁盘空间。