最大内存映射分配大小?

时间:2011-01-14 15:06:02

标签: c++ memory

我的系统: 物理记忆:3gb
Windows XP Service Pack 3(32位) 交换文件大小:30gb

目标:找到我可以在我的机器上分配的最大可能内存映射大小。

当我运行以下代码来分配2gb内存映射文件时,调用失败。

手柄=的CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE | SEC_COMMIT,0,INT_MAX,NULL);

我对此感到非常困惑,因为我可以通过不断调用CreateFileMapping一次100mb来分配一个内存映射文件,直到系统交换文件大小为30gb。

重新启动计算机后,重新运行请求2gb内存映射文件到CreateFileMapping的应用程序,它可以工作,并返回一个有效的句柄。所以这让我有点困惑,在窗户的引擎盖下到底发生了什么?

所以情况是这样的,我可以使用所有系统页面文件(30gb)创建许多小内存映射文件,但是当要求单个分配2gb时,调用失败。重新启动机器并运行相同的应用程序时,调用成功!

一些注意事项:
1)内存映射文件没有加载到proccess虚拟地址空间,还没有查看该文件。
2)操作系统可以将小的100mb内存映射文件分配给30gb的系统页面文件!

现在唯一可以得出的结论是,Windows XP SP3(32位)虚拟内存管理器无法在系统页面文件中成功保留请求的2gb,然后由于系统内存碎片而失败(看起来像它需要保留一个连续的内存分配,即使页面文件是4kb)。重新启动后,我假设系统内存碎片较少,因此允许相同的调用成功并分配大小为2gb的内存映射文件。

我已经运行了一些实验,在运行机器一天后,我启动了一个小应用程序,它将分配一个300mb的内存载文件然后释放它。然后它将增加1mb的大小并再试一次。最后它停在700mb并报告(系统资源不足)。然后我会通过并关闭每个应用程序,这将反过来停止错误消息,它最终继续分配大小为3.5gb的内存映射文件!

所以我的问题是这里发生了什么?虚拟内存管理器必须在内部发生某种类型的内存碎片,因为分配100mbs内存映射文件最多会消耗30gb的系统页面文件(提交限制)。

更新
结论是,如果您要使用INVALID_HANDLE_VALUE创建由系统页面文件支持的大型内存映射文件,则系统页面文件(交换文件)需要调整为所需的大小并且处于大量分配> 2GB !虽然在IO负载很重的情况下它仍然会失败。要解决所有这些问题,您可以使用所需的大小(我做1tb)和内存映射创建自己的文件。

最终更新
我在Windows 7机器上运行了相同的测试,令我惊讶的是它每次都可以工作(直到系统页面文件大小)而不会触及任何东西。所以我想这只是一个错误,大型内存分配在Windows XP上可能比Windows 7更频繁地失败。

3 个答案:

答案 0 :(得分:5)

问题是文件碎片。物理内存(RAM)与此处的任何内容无关。在虚拟内存系统中,从文件系统分配“内存”。物理内存只是加速访问内存的一种优化。

当您请求具有写访问权限的内存映射文件时,系统必须具有一个具有连续页面的文件。系统交换文件通常是碎片。如果对磁盘驱动器进行了很好的碎片整理,您应该能够使用您选择的文件(而不是系统页面文件)创建大型内存映射文件。

因此,如果您确实需要2GB内存映射文件,则需要在安装时在驱动器上创建一个。这将创建连续的2GB文件的问题转移到安装,但一旦创建,你应该没问题。

答案 1 :(得分:3)

  

所以我的问题是这里发生了什么?虚拟内存管理器必须在内部发生某种类型的内存崩溃,因为分配100mbs内存映射文件将消耗最多30gb的系统页面文件(提交限制)。

听起来很对。如果你不需要大量连续的内存块,如果你能在较小的块中获得相同数量的内存,就不要问它们。

  

要找到我可以在我的机器上分配的最大可能内存映射大小。

  • 尝试使用尺寸X.
  • 如果失败,请尝试使用尺寸X / 2并重复。

这会在运行时获得一块,也许不是确切的最大块,但是在2倍之内。

答案 2 :(得分:0)

让我们占据Windows开发人员的位置。 假设某些用户执行以下步骤:

  1. 创建内存映射。
  2. 使用敏感数据填充一些内存
  3. 从文件中取消映射
  4. 继续使用记忆
  5. Windows需要卸载这些页面以执行关键任务。
  6. 分辨率 - 映射内存应该是交换的专长。但这并不意味着映射将被交换。