有什么办法强制一个进程的工作集在C + + 1GB?

如果我在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. 

(专家额外) 实验方法学

我编写了一个testingC ++项目来分配100MB的数据,使工作集超过100MB(在Process Explorer中查看),然后释放该内存。 但是,当我释放内存时,操作系统将WorkingSet重新设置为16MB。 如果你愿意,我可以提供我使用的testingC ++项目。

为什么Windows提供一个调用SetProcessWorkingSetSizeEx(),如果它不似乎工作? 我一定做错了什么。

下图显示了当绿线(工作集)从50MB下降到30MB时,软页面错误(红色尖峰)的数量急剧增加。

示例显示工作集减少时软页面错误的增加

更新

最后,我们最终忽视了这个问题,因为它不会影响性能。

更重要的是,SetProcessWorkingSetSizeEx不控制当前的WorkingSet,并且以任何方式与软页面错误相关。 它所做的是防止硬页面错误,通过防止当前工作设置被分页到硬盘驱动器。

换句话说,如果想减less软页面错误,SetProcessWorkingSetSizeEx绝对没有效果,因为它指的是硬页面错误。

在“Windows通过C / C ++”(Richter)中有一个伟大的写法,Windows如何处理内存。

页面错误很便宜,而且是可以预料的。 实时应用程序,高端游戏,高强度处理和蓝光播放都可以全速工作在页面错误状态。 页面错误不是您的应用程序运行缓慢的原因。

要找出您的应用程序为什么很慢,您需要对应用程序进行一些应用程序分析。

要特别回答你的问题 – 当你刚才有一个GC.Collect()不是页面错误时发生的页面错误,它们是由GC刚刚分配的事实引起的按需求零页面错误一个新的大块需求归零页面来移动你的对象。 需求零页不会从您的页面文件服务,并且不会产生任何磁盘成本,但它们仍然是页面错误,因此它们显示在您的图表上。

一般来说,Windows比您更好地管理您的系统资源,并且它的默认值是针对普通程序的平均情况进行高度调整的。 从你的例子中可以清楚地看到你正在使用一个垃圾收集器,因此你已经把处理工作集和虚拟内存等任务交给了GC实现。 如果SetProcessWorkingSetSize是一个很好的API调用来提高GC性能,那么GC实现就可以做到这一点。

我的建议是配置你的应用程序。 托管应用程序放慢的主要原因是编写错误的托管代码 – 而不是GC减慢你的速度。 通过使用诸如Future和BackgroundWorker之类的东西来改善算法的大O性能,卸载昂贵的工作,并尽量避免对网络进行同步请求 – 但最重要的是,快速获取应用程序的关键是分析它。