6

我们的服务往往在晚上在我们客户的服务器上睡着,然后很难醒来。似乎发生的情况是,有时数百 MB 的进程堆被移动到交换文件中。这发生在晚上,当我们的服务未被使用,而其他服务被安排运行(数据库备份、反病毒扫描等)时。发生这种情况时,在几个小时不活动后,对服务的第一次调用最多需要几分钟(后续调用需要几秒钟)。

我很确定这是虚拟内存管理的问题,我真的很讨厌强迫操作系统将我们的服务保留在物理内存中的想法。我知道这样做会损害服务器上的其他进程,并降低整体服务器吞吐量。话虽如此,我们的客户只是希望我们的应用程序能够响应。他们不在乎夜间工作是否需要更长的时间。

我隐约记得有一种方法可以强制 Windows 将页面保留在物理内存上,但我真的很讨厌这个想法。我更倾向于一些内部或外部的看门狗,它们将启动更高级别的功能(已经有一些内部调度程序做的很少,并且没有区别)。如果有提供这种服务的第 3 方工具会同样好。

我很想听听针对此类问题的任何意见、建议和常见解决方案。该服务是用VC2005编写的,运行在Windows服务器上。

4

5 回答 5

8

正如您所提到的,强制应用程序留在内存中并不是在机器上共享资源的最佳方式。您可能会发现效果很好的一个快速解决方案是简单地安排一个事件,在您的客户开始使用它之前,每天早上在特定时间唤醒您的服务。您可以使用简单的脚本或 EXE 调用在 Windows 任务计划程序中安排它。

于 2009-05-07T08:55:04.800 回答
2

我并不是说你想这样做,或者说这是最佳实践,但你可能会发现它对你来说已经足够好了。它似乎符合您的要求。

摘要:定期触摸流程中的每一页,一次一页。

一个在后台运行并每 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)) 来避免异常处理程序,因为应用程序中的其他线程可能正在同时修改内存保护。如果您因此而陷入困境,几乎不可能确定原因(这很可能是不可重复的竞争条件),所以不要浪费时间。

当然,您可能希望在白天关闭此线程并仅在您的空闲时间运行它。

于 2010-03-16T17:44:01.670 回答
1

第三种方法可能是让您的服务运行一个线程,该线程执行一些微不足道的操作,例如增加一个计数器,然后休眠相当长的一段时间,比如 10 秒。Thios 对其他应用程序的影响应该很小,但至少可以保持您的一些页面可用。

于 2009-05-07T09:02:29.807 回答
1

要确保的另一件事是您的数据已本地化。

换句话说:你真的需要全部 300 MiB 的内存才能做任何事情吗?是否可以重新排列您使用的数据结构,以便任何特定的请求都可以只用几兆字节来满足?

例如

  • 如果您的 300 MiB 堆内存包含面部识别数据。数据内部是否可以进行排列,使男性和女性的人脸数据存储在一起?或者大鼻子与小鼻子是分开的?

  • 如果它有某种逻辑结构,它可以排序吗?以便可以使用二进制搜索跳过很多页面?

  • 如果它是专有的、内存中的数据库引擎,是否可以更好地对数据进行索引/集群以不需要这么多的内存页面命中?

  • 如果它们是图像纹理,常用纹理可以彼此靠近吗?

您真的需要全部 300 MiB 的内存才能做任何事情吗?如果没有所有数据都回到内存中,您就无法服务请求?


否则:计划任务在 6 ᴀᴍ 唤醒它。

于 2010-03-16T18:15:13.440 回答
0

在成本方面,最便宜和最简单的解决方案可能只是为该服务器购买更多 RAM,然后您可以完全禁用页面文件。如果您运行的是 32 位 Windows,只需购买 4GB 的 RAM。然后整个地址空间将由物理内存支持,页面文件无论如何都不会做任何事情。

于 2009-05-07T08:59:18.033 回答