我有一台服务器,我在其中运行工作进程,这些进程映射了几个相当大的只读“字典”文件(总共约 8GB)。测试表明,它们只主动访问这些文件中约 1GB 大小的页面。在同一台服务器上,我运行另一个进程,该进程按顺序读取一个大文件,合并一些更新,并将结果写入这个大文件的新版本。除了这个“合并”进程和“工作”进程之外,服务器上没有其他主要活动。因此,通常情况下,工作进程应该是 CPU 密集型的,而合并进程应该是磁盘密集型的。但我看到的是,工作进程不断因重大页面错误而阻塞。合并使用了大约 20GB 的 RSS,而机器有 48GB。有 4 个工作进程。他们每个都有 2GB RSS,共享的只有 600MB(而不是预期的 1GB 热页面)。不知何故,其余内存大部分被 fs 缓存使用。有没有办法将我映射的文件的热页面“优先”到内存中?我尝试了 madvise(MADV_WILLNEED),但似乎没有帮助。也许有使用 cgroups 或 sysctls 的解决方案?
$ 免费 已使用的、可用的、缓存的共享缓冲区总数 内存:49324064 48863392 460672 0 22520 25409896 -/+ 缓冲区/缓存:23430976 25893088 交换:0 0 0 $ uname -a Linux dev-kiwi02 3.2.0-25-server #40-Ubuntu SMP 2012 年 5 月 25 日星期五 13:12:35 UTC x86_64 GNU/Linux
PS 已经在 StackOverflow 上问过这个问题,但看起来 ServerFault 更合适。
答案1
您可能需要的是 mlock(),而不是 madvise()。Madvise 太“弱”了;mlock 会将内存锁定在内核中。假设您有足够的 RAM 并且只锁定“热”页面(而不是整个 8GB),那么这对您的设置来说应该不是问题。
另一个看似违反直觉的解决方案是禁用交换。您的机器有 48GB;减去 4 个工作程序、共享数据和您的操作系统,您仍然有 > 35 GB 的剩余空间。您写道,合并程序按顺序读取文件并插入一些条目;因此,我假设您不需要将大文件保存在内存中,但也可以按顺序将其写出;您只需将所有更新加载到内存中,这应该不是问题。