是否可以在 Linux 上禁用对 mmap 文件的不必要的磁盘写入?

是否可以在 Linux 上禁用对 mmap 文件的不必要的磁盘写入?

我想知道是否有一种方法可以阻止 Linux 定期将 mmap 文件同步到磁盘,同时仍然允许操作系统在物理内存紧张时回写。

我正在编写处理大图像的应用程序,图像太大以至于可能需要几倍的交换空间量。当交换空间耗尽时,这可能会导致意外的 OOM 崩溃。

不使用交换区分配大内存对象的一种简单方法是调用 mmap()。这个调用使用起来非常简单,并且工作正常,但是有一个严重影响性能的主要问题:操作系统会定期从 mmap 区域写出脏页。

对于我的应用程序,这会将 CPU 利用率从大约 2900% 降低到大约 700%,使进程速度减慢 4 倍。

过去,RedHat 允许通过将操作系统参数 vm.flush_mapped_pa​​ges 设置为 0 来关闭此行为,但此设置不再存在,并且可能会出现意外行为:我不希望仅将操作系统参数调整为使一个进程正常工作。

FreeBSD 允许通过在 mmap 调用中使用 NO_SYNC 标志来关闭此行为,但这在 Linux 中不可用。

以下是我创建 mmap 缓冲区的方法,其中包含处理错误并删除 EINTR 的代码:

        size_t n = 1048576*(size_t)1024*16; // 16G
        int fd = open("mem.bin", O_TRUNC | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
        ftruncate(fd, n);
        void* data = mmap(nullptr, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_HUGE_2MB, fd, 0);
        close(fd);
        unlink("mem.bin");

有没有办法让这些内存有效利用?

答案1

您可以将vm.dirty_writeback_centisecssysctl 设置为 0 以禁用内核的后台脏页刷新器线程。您还需要增加vm.dirty_ratio,以便您的进程不会被迫自行执行脏写回,除非绝对必要。请注意,禁用后台刷新线程后,vm.dirty_background_ratiovm.dirty_background_bytesvm.dirty_expire_centisecssysctls 就无关紧要了。

不幸的是,我不认为可以在每页或每 VMA 的基础上调整写回行为。您只能针对整个 VM 子系统进行调整。

相关内容