注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

widebright的个人空间

// 编程和生活

 
 
 

日志

 
 

windows程序的page fault 和 working set size  

2012-09-07 15:41:07|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

      ?有一个rpc程序,发现client端在本地的 windows xp3运行的时候,在 任务管理器和 process explorer里面看到的 page fault都很高,平均每秒 8000到 15000的样子,看上去是很高了,听说page fault比较影响性能,就去看了一下。   (很奇怪的是在windows  server 2008虚拟机上运行的时候是没有这个page fault,只能说是新的系统 内存管理算法改进了。实际物理内存也和我本地差不多的。)


      用 visutal stuido 2010自带的性能分析工具,sampling 事件里面选 page fault,profile一下,就可以看到page fault对应的源码的地方了。 但是这个很奇怪,后面的自己的源码的frame解析错误了,竟然定位不出来。  只看到是在      "operator new(unsigned int) -> _malloc -> _RtlAllocateHeap@12 -> _RtlpExtendHeap@8"  . 但是谁调用的  "operator new“ 就 没显示出来了,应该是从堆上分配内存的时候导致的.  再用调试的方式,attach的进程上面,然后在 _RtlpExtendHeap@8 函数上设置断点,hit count 设置为每 5000次命中打印一次 堆栈,when hit 里面加上print mesage 加上 $CALLSTACK,把调用堆栈打印出来。还好这里的frame指针解析是正确的,可以看到自己调用哪个的new 的地方了,这个同时写的底层的rpc层的代码,没收到外面来的rpc request,就动态申请一块内存来解析message包格式,很奇怪很多地方都有new 操作的,而且很多频繁的操作,但只有这里的会 触发  page fault,不知很理解他这系统的机制怎么去弄的。  可能用内存池或者 尝试一下tcmalloc之类的针对小内存块的分配器,但不是我写的代码,而且在Windows server 2008问题有没有看到这个现象,就懒的去改了。

 

根据这里的     

 http://msdn.microsoft.com/en-us/library/eye126ky(v=vs.110).aspx 

       Tips for Improving Time-Critical Code


说法,一个page fault可能消耗 一百万个指令周期,代价还是很大的啊!不知道他是指的 从硬盘读page的 hard page fault 还是  只是缺页中断触发的 sofe page fault。

     Working Set

http://msdn.microsoft.com/en-us/library/windows/desktop/cc441804(v=vs.85).aspx 

     Chapter 12 - Detecting Memory Bottlenecks

http://technet.microsoft.com/en-us/library/cc749872.aspx 

  The Basics of Page Faults

http://blogs.technet.com/b/askperf/archive/2008/06/10/the-basics-of-page-faults.aspx 


前两篇微软的文档解释了一下 page fault 产生的原因,看上去和 working set有点关系。后面两篇还教你怎么区分hard和soft page fault,其实应该就是在 系统的 性能监视器或者process explorer 里面 看看有没有写磁盘的操作了。

        看上去我的程序,应该是第一文章说的 “The memory manager trims pages from the working set to create more available memory.” 导致的,每次出现都是在  malloc去申请内存的时候发生的,想扩展堆的时候发生的。看上去和程序的working set size有关。   简单的说 working set size对应物理页,working set size小了,就每次都要申请一个新的page,初次访问page的时候导致的page fault。 我在process explorer里面看  这个程序的 working set size小于 private bytes,而且 任务管理器看到 由于动态申请和分配比较频繁申请和释放,mem delta好像都有200多k的,很奇怪!

         根据文档,好像可以固定用api 设置程序的working set size  最小和最大值。 如果内让系统的分配器保留这个程序working set 为一个比较大的值。应该不会每次分配内存的时候都会导致 page fault了。

        

         根据文档的api说明,发现有一下两个办法来,修改指定进程的  min working set size 和max working size。

   

HANDLE current_process = GetCurrentProcess();
if (GetProcessWorkingSetSize(current_process,&min,&max)){
SIZE_T min ,max;
min = 31457280; // 30 MB
max = 52428800; // 50 MB
HANDLE hToken;
// 方法一
if(OpenProcessToken( current_process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken )) {
TOKEN_PRIVILEGES tp;
LUID luid;

LookupPrivilegeValue(NULL, SE_INC_BASE_PRIORITY_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if( AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES) NULL, 0) ) {
CloseHandle(hToken);
//if(SetProcessWorkingSetSizeEx(current_process,min,max,QUOTA_LIMITS_HARDWS_MIN_ENABLE)) {
if (SetProcessWorkingSetSize(current_process,min,max)) {
max = min;
GetProcessWorkingSetSize(current_process,&min,&max);
}
} else {
CloseHandle(hToken);
}


}
}
// 方法二
JOBOBJECT_BASIC_LIMIT_INFORMATION job_limit_info;
job_limit_info.LimitFlags = JOB_OBJECT_LIMIT_WORKINGSET;
job_limit_info.MinimumWorkingSetSize = 31457280; // 30 MB
job_limit_info.MaximumWorkingSetSize = 52428800; // 50 MB
HANDLE hjob = CreateJobObject(NULL,"SMPP adpater");
AssignProcessToJobObject(hjob,current_process);
if (SetInformationJobObject(hjob,JobObjectBasicLimitInformation,&job_limit_info,sizeof(job_limit_info))) {
::MessageBoxA(NULL, "ok to change the working set size","debug",MB_OK);
}




不过测试时候发现,这个虽然修改后,在 process explorer里面看到 working set size 的最大和最小值都被修改了,但 working set size根本不受这两个参数影响。working set size还是很小,而且page fault 还是很高。后来才看到解析 “Calls to SetProcessWorkingSetSize by an individual process are ignored unless the process is just trying to empty its working set. To set this limit, specify the JOB_OBJECT_LIMIT_WORKINGSET flag in the LimitFlags member.“   在微软的一个古老的网页上有,网上搜索一下可以找到这句话。靠,相应的api对应的页面却上没有说明,太坑人了啊! SetProcessWorkingSetSize 唯一做的就是用来 缩小你的working set size,系统的内存分配系根本就不理会这两个参数。系统好像也没有提供调整内存分配器的接口吧? 

 

        看来这个page falut问题是不能解决了,只能写代码的时候内存分配写的好一点吧。  看到有人说sofe page fault 影响不大,就算了吧。不过我觉得多少还是有些影响的吧,切换到中断,准备一下页表映射,还是很浪费时间的吧。好在程序 在windows server 2008上面看起来没有问题, working set size那些看起来也很正常,没有本地的page fault。不知道什么原因,想windows 这汇总闭源的文件系统就是不爽啊。你很难去分析底下的问题,要是linux就好多了。



  评论这张
 
阅读(1050)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017