用于虚拟内存管理的新 Windows 8.1 API:`DiscardVirtualMemory()` 与 `VirtualAlloc()` 和 `MEM_RESET` 和 `MEM_RESET_UNDO`
New Windows 8.1 APIs for virtual memory management: `DiscardVirtualMemory()` vs `VirtualAlloc()` and `MEM_RESET` and `MEM_RESET_UNDO`
Windows 8.1/Server 2012RC2 刚刚为虚拟内存管理引入了新的 APIs:OfferVirtualMemory()
、ReclaimVirtualMemory()
、DiscardVirtualMemory()
,它们的用法是很简单,只要看看他们的名字就可以了。
我无法理解这些 API 与 VirtualAlloc()
以及标志 MEM_RESET
和 MEM_RESET_UNDO
的工作原理,以及它们之间的细微差别。
对于OfferVirtualMemory()
,MSDN 说它与VirtualAlloc()
+MEM_RESET
非常相似,只是它从工作集中删除页面,并限制对页面的进一步访问。
所以,基本上它限制了对页面的访问,如果我想再次访问这些页面,我必须调用 ReclaimVirtualMemory()
。很好,但是 MEM_RESET
不应该也从工作集中删除页面吗?
MEM_RESET
不应该充当 madvise(2)
的 POSIX MADV_DONTNEED
标志,它基本上从进程的页面表中删除页面,如果我将来再次访问这些页面,访问将产生软故障,这些页面将再次重新分配,初始化为零。
如果这是真的,当然,页面会从进程的工作集中删除,因为它们基本上会被释放,即使进程保持分配的虚拟地址,并看到它们“已提交”。
现在,让我们看看 DiscardVirtualMemory()
:这里 MSDN 没有提到 MEM_RESET
标志,但是如果我阅读这个 API 的描述,似乎 真的 与 VirtualAlloc()
+MEM_RESET
.
相同
那么,有谁知道这些 API 之间是否存在一些差异,这些细微差异的正确用例是什么?如果他们引入了一个像DiscardVirtualMemory()
这样的全新的API,应该与旧方法有一些区别。
如果我想从 POSIX 移植一个应用程序,它使用 madvise(2)
与 MADV_DONTNEED
和 MADV_WILLNEED
,模仿这个 [=62= 的最佳方法是什么] 行为?到目前为止,我对 MADV_DONTNEED
使用 VirtualAlloc()
+MEM_RESET
,对 MADV_WILLNEED
使用 VirtualAlloc()
+MEM_RESET_UNDO
。可以吗,或者我可以用那些新的 APIs 做得更好?
When the region of memory is again accessed by the application, the
backing RAM is restored, and the contents of the memory is undefined.
如果我从字里行间看出,
- 当您访问它时,其中的某些内容可能仍然存在
- 允许在这些页面提交时为您提供垃圾初始化页面
- 如果机器实际上受内存限制,某些页面有时可能会被零初始化
如果您使用较旧的 API 重置虚拟地址范围,则不会发生这种情况。在这种情况下,可以保证在您稍后访问这些页面时提供零初始化页面。
这使得 windows 可以减少对归零页面池的压力,当程序想要更好时,并告诉 windows 它可以丢弃一些释放的内存范围.
Windows 8.1/Server 2012RC2 刚刚为虚拟内存管理引入了新的 APIs:OfferVirtualMemory()
、ReclaimVirtualMemory()
、DiscardVirtualMemory()
,它们的用法是很简单,只要看看他们的名字就可以了。
我无法理解这些 API 与 VirtualAlloc()
以及标志 MEM_RESET
和 MEM_RESET_UNDO
的工作原理,以及它们之间的细微差别。
对于OfferVirtualMemory()
,MSDN 说它与VirtualAlloc()
+MEM_RESET
非常相似,只是它从工作集中删除页面,并限制对页面的进一步访问。
所以,基本上它限制了对页面的访问,如果我想再次访问这些页面,我必须调用 ReclaimVirtualMemory()
。很好,但是 MEM_RESET
不应该也从工作集中删除页面吗?
MEM_RESET
不应该充当 madvise(2)
的 POSIX MADV_DONTNEED
标志,它基本上从进程的页面表中删除页面,如果我将来再次访问这些页面,访问将产生软故障,这些页面将再次重新分配,初始化为零。
如果这是真的,当然,页面会从进程的工作集中删除,因为它们基本上会被释放,即使进程保持分配的虚拟地址,并看到它们“已提交”。
现在,让我们看看 DiscardVirtualMemory()
:这里 MSDN 没有提到 MEM_RESET
标志,但是如果我阅读这个 API 的描述,似乎 真的 与 VirtualAlloc()
+MEM_RESET
.
那么,有谁知道这些 API 之间是否存在一些差异,这些细微差异的正确用例是什么?如果他们引入了一个像DiscardVirtualMemory()
这样的全新的API,应该与旧方法有一些区别。
如果我想从 POSIX 移植一个应用程序,它使用 madvise(2)
与 MADV_DONTNEED
和 MADV_WILLNEED
,模仿这个 [=62= 的最佳方法是什么] 行为?到目前为止,我对 MADV_DONTNEED
使用 VirtualAlloc()
+MEM_RESET
,对 MADV_WILLNEED
使用 VirtualAlloc()
+MEM_RESET_UNDO
。可以吗,或者我可以用那些新的 APIs 做得更好?
When the region of memory is again accessed by the application, the backing RAM is restored, and the contents of the memory is undefined.
如果我从字里行间看出,
- 当您访问它时,其中的某些内容可能仍然存在
- 允许在这些页面提交时为您提供垃圾初始化页面
- 如果机器实际上受内存限制,某些页面有时可能会被零初始化
如果您使用较旧的 API 重置虚拟地址范围,则不会发生这种情况。在这种情况下,可以保证在您稍后访问这些页面时提供零初始化页面。
这使得 windows 可以减少对归零页面池的压力,当程序想要更好时,并告诉 windows 它可以丢弃一些释放的内存范围.