我们的服务在我们客户的服务器的晚上往往会睡着,然后很难醒来。 看起来会发生的是,有时几百MB的进程堆被移动到交换文件中。 这发生在晚上,当我们的服务没有被使用,其他人被安排运行(数据库备份,AV扫描等)。 发生这种情况时,经过几个小时的不活动之后,首次拨打该服务需要花费几分钟时间(因此呼叫需要几秒钟)。
我很确定这是一个虚拟内存pipe理的问题,我真的很讨厌迫使操作系统把我们的服务保留在物理内存中的想法。 我知道这样做会损害服务器上的其他进程,并降低整体服务器的吞吐量。 说了这么多,我们的客户只是希望我们的应用程序能够响应。 他们不在乎夜间工作是否需要更长时间。
我隐约记得有一种方法可以强制Windows将页面保存在物理内存中,但是我真的很讨厌这个想法。 我更倾向于一些内部或外部的看门狗,它们会启动更高级别的function(已经有一些内部调度程序几乎没有什么区别)。 如果有第三方工具提供这种服务是一样的好。
我很乐意听到这类问题的任何意见,build议和共同的解决scheme。 该服务使用VC2005编写,并在Windows服务器上运行。
正如您所提到的,强制应用程序保留在内存中并不是在机器上共享资源的最佳方式。 一个快速的解决方案,你可能会发现很好的做法是简单地安排一个事件,在客户开始使用它之前每天早上在特定的时间唤醒你的服务。 您可以使用简单的脚本或EXE调用将其安排在Windows任务计划程序中。
我并不是说你想这样做,或者说这是最好的做法,但是你可能会发现它对你来说足够好。 它似乎符合你所要求的。
简介:定期在页面上触摸过程中的每个页面。
那么在后台运行的线程每隔N秒唤醒一次呢? 每次唤醒页面时,它都会尝试从地址X中读取。如果您读取了错误的地址,则尝试将受到异常处理程序的保护。 然后按页面的大小增加X.
4GB有65536页,3GB有49152页,2GB有32768页。 将您的空闲时间(通宵停滞时间)划分为您想要(尝试)击打每一页的频率。
BYTE *ptr; ptr = NULL; while(TRUE) { __try { BYTE b; b = *ptr; } __except(EXCEPTION_EXECUTE_HANDLER) { // ignore, some pages won't be accessible } ptr += sizeofVMPage; Sleep(N * 1000); }
您可以从GetSystemInfo()返回的结果中的dwPageSize值中获取sizeOfVMPage值。
不要试图通过使用if(!IsBadReadPtr(ptr))来避免异常处理程序,因为应用程序中的其他线程可能会同时修改内存保护。 如果因为这个原因而变得不稳定,几乎不可能确定为什么(这很可能是一个不可重复的竞赛条件),所以不要浪费时间。
当然,你希望在白天关闭这个线程,并且只能在死机时运行它。
第三种方法可以让你的服务运行一个线程,做一些微不足道的事情,比如增加一个计数器,然后睡一个相当长的时间,比如10秒。 Thios应该对其他应用程序的影响最小,但至少可以保留一些可用的页面。
另一件事是确保你的数据是本地化的。
换句话说,在你做任何事情之前,你真的需要所有300MB的记忆吗? 你可以重新安排你使用的数据结构,以便任何特定的请求可以满足只有几兆字节?
例如
如果你的300MB的堆内存包含面部识别数据。 数据是否可以在内部进行排列,以便将男性和女性的脸部数据存储在一起? 或者大嘴巴和小鼻子是分开的?
如果它有某种逻辑结构,它可以被排序吗? 所以二进制搜索可以用来跳过很多页面?
如果是专有的,内存中的数据库引擎,数据可以更好地被索引/聚集到不需要如此多的内存页面命中?
如果他们是图像纹理,常用的纹理可以彼此靠近吗?
在你做任何事情之前,你真的需要所有300MB的记忆吗? 没有所有的数据回到内存你不能服务请求?
否则:在6ᴀᴍ的计划任务将其唤醒。
在成本方面,最便宜和最简单的解决方案可能只是为该服务器购买更多的RAM,然后就可以完全禁用页面文件。 如果你正在运行32位Windows,只需购买4GB的RAM。 那么整个地址空间将被物理内存所支持,并且页面文件将不会做任何事情。