使或强制 tmpfs 在文件缓存之前进行交换

使或强制 tmpfs 在文件缓存之前进行交换

考虑以下场景。你有一个慢的安装 Linux 的只读介质(例如写保护的拇指驱动器、CD/DVD 等)(本身不是 Live CD,而是普通版本),并在没有其他存储形式的计算机上使用它。它很慢,因为它是 USB 2。根文件系统安装为overlayfs,以便它可以“写入”日志和您所做的许多其他临时工作,但所有写入都会写入RAM(tmpfs upperdir)。对于 Live 发行版来说,这是非常典型的场景。

由于没有其他形式的存储,所以swap挂载在zram上。因此,当 Linux 决定交换时,它会压缩这些页面并将它们仍然存储在 RAM 中,但至少它们被压缩了。这实际上是不错的,因为大多数应用程序的 RAM 都很容易压缩(RAM 通常在数据上非常冗余,因为它意味着“快”)。这适用于应用程序内存,但不适用于 tmpfs。

事情是这样的:zram 是快速地,难以置信。另一方面,拇指驱动器速度很慢。假设它是 20 MiB/s,相比之下确实很慢。您可以在这里看到问题以及为什么内核不会做正确的事情。

注意这个问题是不是的重复如何使 TMPFS 内的文件更有可能交换。问题几乎相同,但我对该问题的答案不满意,抱歉。内核肯定是这样的不是自己做“正确的事”,无论如何聪明的设计它的人是。我不喜欢人们不了解情况并认为自己更了解情况。他们迎合一般情况。这就是 Linux 如此可调整的原因,因为无论它多么聪明,它都无法预测它的用途。

例如,我可以(并且确实)设置虚拟机交换性(/proc/sys/vm/swappiness) 到 100,这告诉它积极交换应用程序内存并保留文件缓存。这个选项很好,但不幸的是它并不是一切。

我希望它优先保留文件缓存处理交换时超过任何其他 RAM 使用。这是因为删除文件缓存会导致它必须从慢速 20 MiB/s 驱动器中读回,这要慢得多。很多比交换到 zram 慢。对于应用程序,vm.swappiness 有效,但不适用于 tmpfs。

tmpfs 作为页缓存挂载,因此与文件缓存具有相同的优先级。如果您从 tmpfs 读取文件,它将优先于较旧的文件缓存条目(最近使用的)。但这很糟糕,内核清楚才不是在这里做正确的事。应该考虑到将 tmpfs 交换为 zram 会比文件缓存“最近使用”要好得多,因为从驱动器读取数据非常慢。

因此,我需要明确告诉它与文件缓存相比更频繁地从 tmpfs 进行交换:它应该比 tmpfs 更保留文件缓存。 /proc/sys/vm 中有很多选项,但我找不到任何相关选项。真是令人失望。

如果做不到这一点,有没有办法告诉内核某些设备/驱动器比其他设备/驱动器慢得多,并且它应该更愿意为它们保留缓存而不是其他设备/驱动器? tmpfs 和 zram 速度很快。拇指驱动器不是。我可以告诉内核这个信息吗?

如果它对所有驱动器都一视同仁,它本身就无法做“正确的事情”。将 tmpfs 交换到 zram 等快速驱动器比从慢速驱动器删除缓存要快得多,即使最近使用了 tmpfs。

当它用完可用内存时,它将由于交换性而开始交换应用程序内存(好),或者删除旧文件缓存(坏)。如果我最终重新读取这些文件,速度会非常慢。比决定交换一些 tmpfs(即使最近使用过)然后再次读取要慢得多。因为 zram 快了一个数量级。

答案1

增加交换性值使内核更愿意交换 tmpfs 页面,而不太愿意从不受交换支持的其他文件系统中逐出缓存页面。

由于 zram swap 比拇指驱动器更快,因此理想情况下您希望将 swappiness 提高到 100 以上。这仅在内核版本 5.8 或更高版本中可行。 Linux 5.8 允许将 swappiness 设置为最大 200。

对于内存交换,例如 zram 或 zswap,可以考虑超过 100 的值。例如,如果针对交换设备的随机 IO 平均比来自文件系统的 IO 快 2 倍,则交换性应为 133 (x + 2x = 200, 2x = 133.33)。

--文档/管理指南/sysctl/vm.rst


进一步阅读

tmpfs 的处理方式与任何其他可交换内存相同

查看内核提交“vmscan:将 LRU 列表拆分为匿名和文件集”——

将 LRU 列表分为两部分,一组用于由真实文件系统(“文件”)支持的页面,一组用于由内存和交换(“匿名”)支持的页面。后者包括 tmpfs。

- 以及代码linux-4.16/mm/vmscan.c:2108-

/*
 * Determine how aggressively the anon and file LRU lists should be
 * scanned.  The relative value of each set of LRU lists is determined
 * by looking at the fraction of the pages scanned we did rotate back
 * onto the active list instead of evict.
 *
 * nr[0] = anon inactive pages to scan; nr[1] = anon active pages to scan
 * nr[2] = file inactive pages to scan; nr[3] = file active pages to scan
 */
static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
               struct scan_control *sc, unsigned long *nr,
               unsigned long *lru_pages)
{
    int swappiness = mem_cgroup_swappiness(memcg);

...

    /*
     * With swappiness at 100, anonymous and file have the same priority.
     * This scanning priority is essentially the inverse of IO cost.
     */
    anon_prio = swappiness;
    file_prio = 200 - anon_prio;

Linux 5.8 允许交换性值最大为 200

mm:允许交换,优先于文件工作集回收匿名

随着快速随机 IO 设备(SSD、PMEM)和内存中交换设备(例如 zswap)的出现,交换可能比文件系统快得多,并且交换比抖动文件系统缓存更可取。

允许设置 swappiness(定义页面缓存和交换支持页面之间缓存未命中的粗略相对 IO 成本),以通过配置交换首选范围来反映此类情况。

这是 Linux 5.8 中一系列补丁的一部分。在以前的版本中,Linux“主要采用页面缓存并推迟交换,直到虚拟机面临严重的内存压力”。这是因为“算法发展过程中旋转驱动器的寻道成本很高,这也意味着错误可能会因过于激进的交换(主要是随机 IO)而很快导致锁定。”

本系列旨在解决这个问题。自从提交(“a528910e12ec mm:基于抖动检测的文件缓存大小调整”)以来,我们对错误 IO 进行了精确跟踪 - 回收错误页面的最终成本。这使我们能够使用基于 IO 成本的平衡模型,该模型在缓存抖动时更积极地扫描匿名内存,同时能够避免不必要的交换风暴。

这些补丁将 LRU 平衡基于每个列表上的失败率,乘以交换设备和文件系统之间的相对 IO 成本(swappiness),以便优化回收以最小化所产生的 IO 成本。

--[PATCH 00/14] mm:基于相对抖动 v2 平衡 LRU 列表

相关内容