【问题标题】:How to prioritize write() over mmap updates (or delay mmap page cache flush)如何将 write() 优先于 mmap 更新(或延迟 mmap 页面缓存刷新)
【发布时间】:2012-06-15 11:55:33
【问题描述】:

我在具有 64G RAM 和大量磁盘空间的 debian-64 上运行专门的数据库守护程序。它使用磁盘上的哈希表(已映射)并通过常规 write() 调用将实际数据写入文件。当进行大量更新时,mmap 的很大一部分会变脏,页面缓存会尝试将其刷新到磁盘,从而产生大量随机写入,这反过来会降低对数据文件的常规(顺序)写入的性能.

如果可以延迟 mmaped 区域的页面缓存刷新,性能将会提高(我假设),因为对脏页的多个(或全部)更改将一次写入而不是每次更新一次(最坏情况,实际上它当然聚合了很多变化)。

所以我的问题是:是否可以延迟内存映射区域的页面缓存刷新?或者是否可以优先考虑常规写入?或者有人有其他想法吗? madvise 和 posix_fadvise 似乎没有任何区别......

【问题讨论】:

    标签: linux memory-management mmap


    【解决方案1】:

    您可以使用 /proc/sys/vm 中的可调参数。例如,增加dirty_writeback_centisecs 中的值以使 pdflush 唤醒的频率有所降低,增加dirty_expire_centiseconds 以便允许数据在必须写出之前保持更长时间,并增加dirty_background_ratio 以允许更多脏页在必须做某事之前留在 RAM 中。
    请参阅here,了解有关所有值的作用的全面描述。

    请注意,这将影响您机器上的每个进程,但是看看您如何运行一个巨大的数据库服务器,这很可能没有问题,因为您不想运行其他任何东西反正在同一台机器上。

    现在这当然会延迟写入,但它仍然不能完全解决脏页写回与write 竞争的问题(尽管如果有很多更新它可能会崩溃一些写入)。
    但是:可以使用sync_file_range 系统调用来强制开始写出“写入”文件描述符(SYNC_FILE_RANGE_WRITE)上给定范围内的页面。因此,虽然脏页将在稍后的某个未知时间(并且具有更长的宽限期)被写回,但您可以手动启动对您感兴趣的页面的写回。
    这并不能提供任何保证,但它应该正常工作。

    请务必绝对积极地阅读文档,最好阅读两遍。 sync_file_range 如果使用不当,很容易损坏或丢失数据。特别是,您必须确保元数据是最新的并在附加到文件时刷新,否则“成功写入”的数据将在崩溃的情况下“消失”。

    【讨论】:

    • 这听起来很合理(虽然我认为我也必须增加dirty_ratio),我会在接下来的几周内尝试一下,并告诉你结果。谢谢!
    【解决方案2】:

    我会尝试mlock。如果您mlock 相关内存范围,则可能会阻止刷新发生。完成后您可以munlock

    【讨论】:

    • 虽然 mlock 可能会起作用,但这不是通过避免刷新。这是因为物理内存会粘在地址范围内,所以页面不能被盗它们被刷新(并且很长时间没有被引用)之后,确切的问题当然是对哈希表的访问将非常稀疏和虚假:有可能在很长一段时间内都不会引用某些页面(并且会被 LRU 从核心中删除)。 Mlock 可能会工作(如果内存不是太紧的话)
    • 问题不在于它需要从磁盘重新加载哈希表的相关部分(哈希表并不是那么稀疏和大,我尝试了一个一切都适合 ram 的场景,包括数据),问题是页面刷新的实际写入操作会导致大量磁盘 i/o(因为它们经常被弄脏),这会减慢对数据文件的写入速度(当然这是不可避免的,但是问题是它是否可以减轻)
    • 问题是在(好的)哈希表中,访问模式总是分散的。在覆盖 N 个页面的哈希表上发布 N 个更新,将命中大约 (2/3) *N 个页面。只有大约。 N/3 页将不会被点击。避免这种情况的唯一方法是不使用 mmap(或匿名/私有映射),并发明一些其他方法将更新应用到磁盘文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 2015-09-26
    相关资源
    最近更新 更多