内存映射文件是否仍然保留在物理内存中?

6
我有一个使用大量内存映射文件的进程。
问题是这些文件即使机器内存不足,其他进程需要这些内存时,它们仍然保留在物理内存中。
我尝试使用SetProcessWorkingSetSize来限制进程工作集,但无效,进程的工作集仍然会超过最大值。
有没有更好的方法来限制进程的工作集?
我能否更改Windows页面内存映射文件的启发式算法?
4个回答

3

最终使用了暴力 VirtualUnlock。

PROCESS_MEMORY_COUNTERS pmc;
if (GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
        if (pmc.WorkingSetSize > MaxWorkingSetSize)
        {
                VirtualUnlock(FilePtr.pData, MaxWorkingSetSize);
                UnmapViewOfFile(FilePtr.pData);
                CloseHandle(FilePtr.hFileMap);
                CloseHandle(FilePtr.hFile);
        }
}

有趣。出于好奇,你在哪里执行这段代码? - Noldorin
每次访问映射文件时。 - Meidan Alon

2
如果您发现您的内存映射文件进程占用了很多这些页面,那么这意味着操作系统没有需要丢弃任何您的内存映射区域以提供给其他进程使用的内存。那么,如何知道其他进程实际上需要当前用于映射文件的内存?仅仅因为操作系统物理RAM不足并不意味着什么。其他进程必须要求内存才能导致操作系统放弃您的映射页面并向它们提供RAM。
因此,似乎您的mmap-I/O进程正在饥饿地影响着使用内存不太频繁的其他进程。一种方法是在被饥饿的进程中谨慎地锁定内存。请参考win32的VirtualLock。

我知道这是因为我也拥有另一个进程,我看到它有很多页面错误,并且没有使用所需的那么多内存。 - Meidan Alon
但是性能会受到什么影响呢?当操作系统不必将脏页提交到磁盘时,页面错误可能非常便宜。如果您的其他进程使用的内存比您想象的要少,那么显然它实际上并不需要它。 - karunski
我应该提到,另一个进程的性能慢了几个数量级。 - Meidan Alon
好的,你的I/O访问模式导致虚拟内存管理器使其他进程饱受饥饿。回答已编辑。 - karunski
mmf 进程在我启动另一个进程之前已经几分钟没有访问其内存了,这仍然可能是一种饥饿情况吗? - Meidan Alon
是的,很可能。如果没有其他进程需要内存,操作系统就没有理由从RAM中丢弃它。 - karunski

0

请查看我的答案这里;使用VirtualUnlock()函数,您可以手动取消提交MMF的部分;例如,您认为不会很快再次访问的部分。


0
我认为这种行为是由于MMF(内存映射文件)的工作方式所致。看一下这篇博客文章this,它解释了MMF文件如何跳过Windows分页过程,因此不受页面文件支持。相反,MMF本身成为数据备份,这意味着它最终占用更多的RAM,因为它不会被分页出去(嗯,我自己也不太确定,最好读一下博客!)
这里是关于内存映射文件的MSDN文档here's,还有一个与MMF相关的SO问题here's

这篇MSDN文章清楚地表明MMF API位于VMM之上,因此应该能够将页面分页到磁盘并清除未使用的页面。 - Meidan Alon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接