如果我在C++中使用以下调用,我希望该进程的WorkingSet永远不会低于100MB.
但是,即使我拨打此电话,操作系统仍会将工作集修剪回16MB.
通过消除软页面错误,将WorkingSet设置为100MB可以显着提高应用程序的速度(请参见下图).
我究竟做错了什么?
SIZE_T workingSetSizeMB = 100;
int errorCode = SetProcessWorkingSetSizeEx(
GetCurrentProcess(),
(workingSetSizeMB - 1) * 1024 * 1024), // dwMinimumWorkingSetSize
workingSetSizeMB * 1024 * 1024, // dwMaximumWorkingSetSize,
QUOTA_LIMITS_HARDWS_MIN_ENABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE
);
// errorCode returns 1, so the call worked.
Run Code Online (Sandbox Code Playgroud)
(专家额外) 实验方法
我编写了一个测试C++项目来分配100MB的数据,使WorkingSet超过100MB(在Process Explorer中查看),然后释放该内存.但是,一旦我释放了内存,操作系统就会将WorkingSet重新调整为16MB.如果你愿意,我可以提供我用过的测试C++项目.
为什么Windows提供对SetProcessWorkingSetSizeEx()的调用,如果它看起来不起作用?我一定做错了什么.
下图显示了当绿线(工作集)从50MB下降到30MB时,软页面错误(红色峰值)数量急剧增加.

更新
最后,我们最终忽略了这个问题,因为它不会对性能产生太大影响.
更重要的是,SetProcessWorkingSetSizeEx并没有控制当前工作集,并且不以任何方式软页面错误有关.它所做的只是通过阻止当前的WorkingSet被分页到硬盘驱动器来防止硬页面错误.
换句话说,如果想要减少软页面错误,SetProcessWorkingSetSizeEx绝对没有效果,因为它指的是硬页面错误.
在"Windows via C/C++"(Richter)中有一篇很棒的文章,介绍了Windows如何处理内存.
如何为64位.NET进程设置MinWorkingSet和MaxWorking?
ps我可以为32位进程设置MinWorkingSet和MaxWorking集,如下所示:
[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
[DllImport("KERNEL32.DLL", EntryPoint = "GetCurrentProcess", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr MyGetCurrentProcess();
// In main():
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, int.MaxValue, int.MaxValue);
Run Code Online (Sandbox Code Playgroud)