如何限制复制使用的缓存,以便仍有内存可用于其他缓存



基本情况:

我正在 openSUSE 中复制一些 NTFS 磁盘。每个是 2 TB。当我这样做时,系统运行缓慢。

我的猜测:

我相信这可能是由于缓存。Linux 决定丢弃有用的缓存(例如,KDE 4 膨胀、虚拟机磁盘、LibreOffice 二进制文件、Thunderbird 二进制文件等),而是用复制磁盘中的内容填充所有可用内存(总共 24 GB),这些内存只会读取一次,然后写入并且永远不会再次使用。因此,每当我使用这些应用程序(或 KDE 4)时,都需要再次读取磁盘,再次读取磁盘上的膨胀会使事情冻结/打嗝。

由于缓存消失以及这些臃肿的应用程序需要大量缓存的事实,这使得系统非常慢。

由于它是USB,磁盘和磁盘控制器不是瓶颈,因此使用ionice不会使其更快。

我相信这是缓存,而不仅仅是主板太慢,因为如果我停止所有复制,它仍然会断断续续地运行一段时间,直到它重新缓存所有内容。

如果我重新开始复制,则需要一分钟才能再次断断续续。而且,我可以将其限制在 40 MB/s 左右,并且它再次运行得更快(不是因为它缓存了正确的内容,而是因为主板总线为系统磁盘提供了大量额外的带宽)。我可以完全接受主板的 I/O 功能完全消耗的性能损失(这是 100% 使用,这意味着 0% 浪费的功率,这让我很开心),但我不能接受这种缓存机制在这个特定用例中表现如此糟糕。

# free
             total       used       free     shared    buffers     cached
Mem:      24731556   24531876     199680          0    8834056   12998916
-/+ buffers/cache:    2698904   22032652
Swap:      4194300      24764    4169536

我也在 Ubuntu 上尝试了同样的事情,这会导致系统完全挂起。 ;)

澄清一下,我不是在问如何为"系统"留出内存,而是为"缓存"留出内存。我知道缓存内存在需要时会自动返回给系统,但我的问题是它不是为缓存特定内容保留的。

有没有办法告诉这些复制操作来限制内存使用量,以便一些重要的东西保持缓存,因此任何减速都是正常磁盘使用而不是重新读取相同常用文件的结果?例如,是否有允许将每个进程/用户/文件系统的最大内存用作缓存/缓冲区的设置?

nocache 命令是这个问题的一般答案!它也在Debian和Ubuntu 13.10(Saucy Salamander)中。

谢谢,彼得,提醒我们注意 rsync 中的 --drop-cache" 选项。 但这在上游被拒绝了(错误 9560 – 拖放缓存选项),转而支持更通用的解决方案:基于 rsync 的新"nocache"命令与 fadvise。

您只需将"nocache"附加到所需的任何命令。 它还具有用于描述和修改文件缓存状态的良好实用程序。例如,以下是带和不带无缓存的效果:

$ ./cachestats ~/file.mp3
pages in cache: 154/1945 (7.9%)  [filesize=7776.2K, pagesize=4K]
$ ./nocache cp ~/file.mp3 /tmp
$ ./cachestats ~/file.mp3
pages in cache: 154/1945 (7.9%)  [filesize=7776.2K, pagesize=4K]
$ cp ~/file.mp3 /tmp
$ ./cachestats ~/file.mp3
pages in cache: 1945/1945 (100.0%)  [filesize=7776.2K, pagesize=4K]

因此,希望这将适用于其他备份程序(rsnapshot,duplicity,rdiff-backup,amanda,s3sync,s3ql,tar等)和其他您不想破坏缓存的命令。

Kristof Provost 非常接近,但在我的情况下,我不想使用 dd 或编写自己的软件,所以解决方案是在 rsync 中使用"--drop-cache"选项。

自从创建这个问题以来,我已经多次使用它,它似乎完全解决了问题。一个例外是当我使用 rsync 从不支持 "--drop-cache" 的 FreeBSD 机器复制时。所以我写了一个包装器来替换/usr/local/bin/rsync 命令,并删除了该选项,现在它也可以从那里复制。

仍然使用大量内存作为缓冲区,并且似乎几乎没有缓存,但无论如何它都能顺利运行。

$ free
             total       used       free     shared    buffers     cached
Mem:      24731544   24531576     199968          0   15349680     850624
-/+ buffers/cache:    8331272   16400272
Swap:      4194300     602648    3591652

您实际上有两个选择:

  1. 限制最大磁盘缓冲区大小:您看到的问题可能是由默认内核配置引起的,该配置允许使用大量 RAM 进行磁盘缓冲,当您尝试将大量内容写入非常慢的设备时,您最终会获得大量宝贵的 RAM 用于磁盘缓存到速度较慢的设备。

    内核这样做是因为它假设进程在没有被慢速设备减慢时可以继续做事,并且如果需要,可以通过简单地将页面写入存储(慢速 U 盘 - 但内核不考虑该进程的实际性能)来自动释放 RAM。快速修复:

     # Wake up background writing process if there's more than 50 MB of dirty memory
     echo 50000000 > /proc/sys/vm/dirty_background_bytes
     # Limit background dirty bytes to 200 MB (source: http://serverfault.com/questions/126413/limit-linux-background-flush-dirty-pages)
     echo 200000000 > /proc/sys/vm/dirty_bytes
    

    调整数字以匹配您愿意在磁盘写入缓存上花费的 RAM。合理值取决于您的实际写入性能,而不是您拥有的 RAM 量。您应该以勉强有足够的 RAM 进行缓存为目标,以允许设备的完整写入性能。请注意,这是一个全局设置,因此您必须根据您使用的最慢设备进行设置。

  2. 为要保持快速执行的每个任务保留最小内存大小。在实践中,这意味着为您关心的内容创建cgroup,并为任何此类组定义您希望拥有的最小内存。这样,内核就可以根据需要使用剩余的内存。有关详细信息,请参阅此演示文稿: SREcon19 亚太地区 - 大规模 Linux 内存管理:引擎盖下

2022年更新:

您还可以尝试使用以下内容创建新的文件/etc/udev/rules.d/90-set-default-bdi-max_ratio-and-min_ratio.rules

# For every BDI device, set max cache usage to 30% and min reserved cache to 2% of the whole cache
# https://unix.stackexchange.com/a/481356/20336
ACTION=="add|change", SUBSYSTEM=="bdi", ATTR{max_ratio}="30", ATTR{min_ratio}="2"

这个想法是限制每个设备的最大缓存利用率。使用上述限制 (30%),您可以拥有两个完全停止的设备,并且仍有 40% 的磁盘缓存可用于系统的其余部分。如果您有 4 个或更多设备并行停止,即使此解决方法也无法单独提供帮助。这就是为什么我还为每个设备添加了 2% 的最小缓存空间,但我不知道如何检查这是否真的有效。我已经运行这个配置大约半年了,我认为它运行得很好。

有关详细信息,请参阅 https://unix.stackexchange.com/a/481356/20336。

内核无法知道您不会再次使用复制的缓存数据。这是您的信息优势。

但是您可以将交换性设置为 0:sudo sysctl vm.swappiness=0。这将导致 Linux 在将库等写入交换之前删除缓存。

它对我来说也很好用,尤其是与大量 RAM (16-32 GB) 相结合时性能非常高。

如果您使用的是普通的旧cp,这是不可能的,但是如果您愿意自己重新实现或修补它,则在输入和输出文件上设置posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE)可能会有所帮助。

posix_fadvise()告诉内核您的预期访问模式。在这种情况下,您只会使用一次数据,因此缓存它没有任何意义。Linux 内核遵循这些标志,因此它不应该再缓存数据。

尝试使用 dd 而不是 cp

或者mount带有 sync 标志的文件系统。

我不完全确定这些方法是否绕过交换,但可能值得一试。

我正在复制一些NTFS磁盘[...]系统运行缓慢。[...]因为它是 USB [...]

速度减慢是一个已知的内存管理问题。

使用较新的 Linux 内核。较旧的USB数据和"透明大页面"有问题。请参阅此 LWN 文章。最近解决了这个问题 - 请参阅 LinuxChanges 中的"内存管理"。

好的,现在我知道你正在使用rsync,我可以再挖掘一点:

同时使用大量文件时,rsync 似乎无效。他们的常见问题解答中有一个条目,这不是Linux/缓存问题。这是一个占用太多 RAM 的 rsync 问题。

谷歌搜索有人建议将同步拆分为多个rsync调用。

最新更新