如果我在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.
(专家额外) 实验方法
我编写了一个测试C ++项目来分配100MB的数据,使WorkingSet超过100MB(在Process Explorer中查看),然后释放该内存。但是,一旦我释放了内存,操作系统就会将WorkingSet重新调整为16MB。如果你愿意,我可以提供我用过的测试C ++项目。
为什么Windows提供对SetProcessWorkingSetSizeEx()的调用,如果它看起来不起作用?我一定是做错了。
下图显示当绿线(工作集)从50MB降至30MB时,软页面错误(红色峰值)数量急剧增加。
更新
最后,我们最终忽略了这个问题,因为它不会对性能造成太大影响。
更重要的是,SetProcessWorkingSetSizeEx 不控制当前的WorkingSet,并且不以任何方式与软页面错误相关。它所做的就是通过阻止当前的WorkingSet被分页到硬盘驱动器来防止硬页面错误。
换句话说,如果想要减少软页面错误,SetProcessWorkingSetSizeEx绝对没有效果,因为它引用了硬页面错误。
“Windows via C / C ++”(Richter)中有一篇很棒的文章,介绍了Windows如何处理内存。
答案 0 :(得分:4)
页面错误很便宜且可以预期。实时应用程序,高端游戏,高强度处理和BluRay播放都可以快速地以页面错误的方式全速工作。页面错误不是您的应用程序运行缓慢的原因。
要了解应用程序运行缓慢的原因,您需要对应用程序进行一些应用程序分析。
要专门回答您的问题 - 当您刚刚拥有GC.Collect()时发生的页面错误不是页面调入错误,它们是由于GC导致的需求归零页面错误刚刚分配了一个新的大块需求归零页面来移动你的对象。请求零页面不会从您的页面文件中提供服务而且不会产生磁盘成本,但它们仍然是页面错误,因此它们显示在图表上的原因。
作为一般规则,Windows在管理系统资源方面比您更好,并且默认情况下针对普通程序的平均情况进行了高度调整。从您的示例中可以清楚地看出,您正在使用垃圾收集器,因此您已经卸载了处理工作集和虚拟内存等任务以及GC实现。如果SetProcessWorkingSetSize是一个很好的API调用来提高GC性能,那么GC实现就可以做到。
我的建议是分析您的应用。托管应用程序减速的主要原因是编写错误的托管代码 - 而不是GC会降低您的速度。提高算法的大O性能,通过使用Future和BackgroundWorker之类的东西来卸载昂贵的工作,并尽量避免对网络进行同步请求 - 但最重要的是,快速获取应用程序的关键是配置文件它。