我可以配置Linux系统以获得更积极的文件系统缓存吗?


119

我既不用担心RAM的使用(我已经足够了),也不必担心由于意外关机而丢失数据(因为我的电源得到了支持,系统很可靠,数据也不重要)。但是我做了很多文件处理,可能会提高性能。

这就是为什么我想将系统设置为使用更多的RAM进行文件系统的读写缓存,以积极地预取文件(例如,在文件大小正常或至少合理的情况下,预读应用程序访问的整个文件)提前读取其中的很大一部分),并减少刷新缓冲区的频率。如何实现(可能)?

我在XUbuntu 11.10 x86上使用ext3和ntfs(我经常使用ntfs!)文件系统。


6
如果您有大量的RAM,请非常在意性能,而不在乎数据丢失,只需将所有数据复制到RAM磁盘上并从那里进行处理,就可以在崩溃/关机时丢弃所有更新。如果那对您不起作用,则可能需要使“足够”的RAM合格,或者数据的重要性不高。
詹姆斯·扬曼

1
@Nils,计算机是一台笔记本电脑,因此,我相信控制器非常普通。
伊万(Ivan)

1
提高性能的一种方法是跳过数据的持久性。即使某些应用程序要求同步,也只需禁用与磁盘的同步即可。如果您的存储设备断电,这将导致数据丢失。如果仍然要执行此操作,只需执行sudo mount -o ro,nobarrier /path/to/mountpoint或调整/etc/fstab以包括nobarrier您愿意为提高性能而牺牲的任何文件系统。但是,如果您的存储设备装有内置电池(例如Intel 320 SSD系列),则使用nobarrier不会造成数据丢失。
Mikko Rantalainen 2014年

1
在Red Hat Enterprise Linux 6中不再建议使用nobarrier,因为写障碍对性能的负面影响可以忽略不计(大约3%)。写屏障的好处通常超过禁用它们的性能好处。此外,绝对不要在虚拟机上配置的存储上使用nobarrier选项。 access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/...
伊瓦伊洛·Bardarov

1
有两点-1)有一些基于Debian或Ubuntu的Linux发行版,例如Puppy Linux和AntiX Linux,还有许多其他发行版将整个操作系统放在分层的ramdisk分区(即AUFS或overlayfs)中,并进行透明管理。非常快!-2)我们在大型系统的实际设计中发现,向其扔更多的缓存会降低性能。随着存储速度的增加(即SSD),所需的最佳缓存大小会减小。如果没有在您的特定系统上进行实验,就无法知道该大小是多少。如果增加无效,请尝试减少。
DocSalvager

Answers:


106

通常,提高磁盘缓存性能不只是增加文件系统缓存大小,除非整个系统都适合RAM,在这种情况下,您应该使用RAM驱动器(tmpfs这很好,因为在某些情况下,如果需要RAM,它可以回退到磁盘)用于运行时存储(可能还有一个initrd脚本,用于在启动时将系统从存储复制到RAM驱动器)。

您没有告诉您存储设备是SSD还是HDD。这是我发现对我有用的东西(在我的情况下sda是HDD安装在/homesdbSSD安装在/)。

首先优化从存储到缓存的加载部分:

这是我的HDD设置(如果有切换,请确保在BIOS中启用了AHCI + NCQ):

echo cfq > /sys/block/sda/queue/scheduler
echo 10000 > /sys/block/sda/queue/iosched/fifo_expire_async
echo 250 > /sys/block/sda/queue/iosched/fifo_expire_sync
echo 80 > /sys/block/sda/queue/iosched/slice_async
echo 1 > /sys/block/sda/queue/iosched/low_latency
echo 6 > /sys/block/sda/queue/iosched/quantum
echo 5 > /sys/block/sda/queue/iosched/slice_async_rq
echo 3 > /sys/block/sda/queue/iosched/slice_idle
echo 100 > /sys/block/sda/queue/iosched/slice_sync
hdparm -q -M 254 /dev/sda

值得一提的是,HDD的情况fifo_expire_async通常很高(通常为写入状态),并且需要很长时间slice_sync才能使单个进程获得较高的吞吐量(slice_sync如果遇到多个进程并行等待磁盘中的某些数据的情况,则设置为较低的数字)。的slice_idle始终是HDD的一种妥协,但在3-20范围内某处设置应该根据磁盘以及磁盘固件是好的。我倾向于将目标值设置为较低,但将其设置为太低会破坏吞吐量。该quantum设置似乎对吞吐量有很大影响,但请尝试将其保持在尽可能低的水平,以将延迟保持在合理水平。设置quantum太低会破坏吞吐量。3-8范围内的值似乎适用于HDD。读取的最坏情况延迟是(quantum* slice_sync)+(slice_async_rq*slice_async)毫秒(如果我正确理解了内核的行为)。异步方式主要用于写入,因为你愿意推迟写入磁盘,同时设置slice_async_rqslice_async非常低的数字。但是,将slice_async_rq值设置得太低可能会导致读取停止,因为在读取之后无法再延迟写入。我的配置将尝试之后数据传递给内核10秒后最多将数据写入磁盘,但因为你可以容忍的功率损耗数据也设定的损失fifo_expire_async3600000告诉大家,1个小时还好耽搁到磁盘。slice_async不过,请保持较低的值,因为否则可能会导致较高的读取延迟。

hdparm需要使用该命令来防止AAM破坏AHCI + NCQ所允许的大部分性能。如果磁盘发出太多噪音,请跳过此步骤。

这是我的SSD(Intel 320系列)设置:

echo cfq > /sys/block/sdb/queue/scheduler
echo 1 > /sys/block/sdb/queue/iosched/back_seek_penalty
echo 10000 > /sys/block/sdb/queue/iosched/fifo_expire_async
echo 20 > /sys/block/sdb/queue/iosched/fifo_expire_sync
echo 1 > /sys/block/sdb/queue/iosched/low_latency
echo 6 > /sys/block/sdb/queue/iosched/quantum
echo 2 > /sys/block/sdb/queue/iosched/slice_async
echo 10 > /sys/block/sdb/queue/iosched/slice_async_rq
echo 1 > /sys/block/sdb/queue/iosched/slice_idle
echo 20 > /sys/block/sdb/queue/iosched/slice_sync

在此值得注意不同切片设置的较低值。SSD的最重要设置是slice_idle必须设置为0-1。将其设置为零会将所有排序决定移至本机NCQ,而将其设置为1则允许内核对请求进行排序(但如果NCQ处于活动状态,则硬件可能会部分覆盖内核排序)。测试两个值以查看是否可以看到差异。对于Intel 320系列,似乎将设置slide_idle0提供最佳吞吐量,但将其设置为1提供最佳(最低)总体延迟。

有关这些可调参数的更多信息,请参见http://www.linux-mag.com/id/7572/

既然我们已经配置了内核,以合理的性能将内容从磁盘加载到缓存,那么该调整缓存行为了:

根据我已经完成的基准测试,我根本不会打扰任何预先设置的情况blockdev。内核默认设置很好。

将系统设置为优先于交换文件数据而不是应用程序代码(如果您有足够的RAM来保持整个文件系统以及所有应用程序代码应用程序分配的所有虚拟内存在RAM中,这无关紧要)。这样可以减少在不同应用程序之间交换的延迟,而不是从单个应用程序访问大文件的延迟:

echo 15 > /proc/sys/vm/swappiness

如果您希望将应用程序几乎总是保留在RAM中,则可以将其设置为1。如果将其设置为零,除非绝对有必要避免OOM,否则内核将根本不会交换。如果您的内存有限并且要处理大文件(例如,高清视频编辑),那么将其设置为接近100可能是有意义的。

如今(2017年),我希望如果有足够的RAM,则完全不进行交换。如果没有交换,通常会在长时间运行的台式机上丢失200-1000 MB的RAM。我愿意为此付出很多,以避免最坏情况下的延迟(在RAM满时交换应用程序代码)。实际上,这意味着我更喜欢OOM Killer而不是交换。如果允许/需要交换,则可能还需要增加交换量/proc/sys/vm/watermark_scale_factor,以避免某些延迟。我建议使用100到500之间的值。您可以将此设置视为交易CPU使用率,以降低交换延迟。默认值为10,最大可能值为1000。(根据内核文档)较高的值应导致kswapd进程的CPU使用率较高,并且总交换延迟较低。

接下来,告诉内核优先于在文件中保留目录层次结构而不是文件内容,以防万一需要释放一些RAM(同样,如果所有内容都适合RAM,则此设置不执行任何操作):

echo 10 > /proc/sys/vm/vfs_cache_pressure

设置 vfs_cache_pressure设置为低值是有意义的,因为在大多数情况下,内核需要先了解目录结构,然后才能使用高速缓存中的文件内容,并且过早刷新目录高速缓存将使文件高速缓存几乎一文不值。如果您有很多小文件(我的系统大约有150K 10兆像素的照片并算作“很多小文件”系统),请考虑使用此设置将其降至1。永远不要将其设置为零,否则即使系统内存不足,目录结构也始终保留在内存中。仅当您只需要不断读取少量大文件时,才将此值设置为大值才有意义(同样,没有足够RAM的高清视频编辑就是一个例子)。官方内核文档说:

例外:如果您确实有大量的文件和目录,并且很少触摸/读取/列出所有设置vfs_cache_pressure高于100的文件,则可能是明智的。仅当您没有足够的RAM且无法将整个目录结构保留在RAM中并且仍然有足够的RAM用于常规文件缓存和进程(例如,具有大量存档内容的公司范围内的文件服务器)时,这才适用。如果您觉得需要增加到vfs_cache_pressure100以上,则说明运行时没有足够的RAM。增加vfs_cache_pressure可能会有所帮助,但唯一真正的解决方法是获得更多的RAM。已经vfs_cache_pressure设置为高数平均牺牲性能为整体具有更稳定的性能(即,你能避免非常糟糕的最坏情况的行为,但不得不面对较差总体性能)。

最后告诉内核放缓是的写作过程之前,使用最多的RAM作为高速缓存写入,99%和指示内核使用最多的RAM 50%(默认为dirty_background_ratio10)。警告:我个人不会这样做,但是您声称有足够的RAM并且愿意丢失数据。

echo 99 > /proc/sys/vm/dirty_ratio
echo 50 > /proc/sys/vm/dirty_background_ratio

并告诉您1h的写延迟甚至可以开始在磁盘上写东西(再次,我不会这样做):

echo 360000 > /proc/sys/vm/dirty_expire_centisecs
echo 360000 > /proc/sys/vm/dirty_writeback_centisecs

如果将所有这些放在/etc/rc.local最后并包括以下内容,则引导后所有内容将尽快存储在缓存中(仅在文件系统确实适合RAM时才这样做):

(nice find / -type f -and -not -path '/sys/*' -and -not -path '/proc/*' -print0 2>/dev/null | nice ionice -c 3 wc -l --files0-from - > /dev/null)&

还是有点简单的替代方法可能更好地工作(仅缓存/home/usr,如果仅仅做到这一点你/home/usr真正适合在RAM中):

(nice find /home /usr -type f -print0 | nice ionice -c 3 wc -l --files0-from - > /dev/null)&

3
消息灵通且总体上比接受的答案好得多!这个被低估了……我想大多数人都只是想要简单的说明而又不花心地去理解他们的实际工作 ……
Vladimir Panteleev 2013年

2
@Phpdevpad:另外,问题是“我不关心RAM的使用情况”,我认为任何Maemo设备都不符合要求。
Mikko Rantalainen

1
Noop或截止日期不是更好的SSD调度程序吗?
rep_movsd

1
@rep_movsd我一直只使用intel SSD驱动器,但至少这些驱动器仍然足够慢,无法通过更智能的调度程序(例如CFQ)获得更好的整体性能。我猜想,如果您的SSD驱动器可以处理超过100K的随机IOPS,则即使在CPU速度较快的情况下,使用noop还是使用截止时间也是有意义的。所谓“快速CPU”,是指至少有多个3GHz内核仅可用于IO。
Mikko Rantalainen

1
您还可以从vm内核文档中了解这些vm可调参数。
joeytwiddle

16

首先,我不建议您继续使用NTFS,因为在Linux中执行ntfs随时可能会导致性能和安全问题。

您可以执行以下几项操作:

  • 使用一些较新的fs,例如ext4btrfs
  • 尝试更改您的io调度程序,例如 bfq
  • 关闭交换
  • 使用一些自动预加载器,例如 preload
  • systemd引导时使用类似预加载的内容
  • ...还有更多

也许您想尝试一下:-)


1
我已经完全从NTFS移至ext4,仅将NTFS分区保留为Windows系统分区。但这给我带来了许多不便,我又转而使用NTFS作为主要数据分区(我在其中存储所有文档,下载,项目,源代码等)的文件系统。我不放弃重新考虑分区结构和工作流程(以使用更少的Windows),但是现在放弃NTFS似乎不是一个现实的选择。
伊万

如果您也必须在Windows内部使用数据,则NTFS可能是唯一的选择。(如果您可以将Windows用作Linux中的VM,则可以使用许多其他选项)
Felix Yan

1
总结一下NTFS这些所谓的问题是很有用的。
underscore_d 2015年

2
除了性能外,Linux上的NTFS几乎可以接受。考虑到该问题是专门关于提高文件系统性能的,因此NTFS应该是第一件事。
米科·兰塔莱宁

即使btrfs是最近设计的文件系统,如果需要性能,我也会避免这种情况。我们一直在运行btrfsext4文件系统相同的系统,并且ext4在现实世界中大获全胜(btrfs似乎需要大约4倍的CPU时间ext4才能达到相同的性能水平,并且单个逻辑命令会导致更多的磁盘操作)。根据工作负荷,我建议ext4jfsxfs任何性能要求苛刻的工作。
Mikko Rantalainen

8

提前阅读:

在32位系统上:

blockdev --setra 8388607 /dev/sda

在64位系统上:

blockdev --setra 4294967295 /dev/sda

写在缓存后面:

echo 100 > /proc/sys/vm/dirty_ratio

这将最多使用100%的可用内存作为写缓存。

或者,您可以全力以赴并使用tmpfs。仅当您有足够的RAM时才有意义。放进去/etc/fstab。将100G替换为物理RAM的数量。

tmpfs /mnt/tmpfs tmpfs size=100G,rw,nosuid,nodev 0 0

然后:

mkdir /mnt/tmpfs; mount -a

然后使用/ mnt / tmpfs。


5
预读3GB或2TB?真?您甚至不知道这些选项会做什么?
Cobra_Fast 2013年

1
@Cobra_Fast你知道这意味着什么吗?我真的不知道,我现在很感兴趣。
syss

3
@syss预读设置保存为内存“块”数,而不是字节或位。在某些情况下,一个块的大小是在内核编译时确定的(因为预读块是存储块)或在文件系统创建时确定。不过,通常情况下,1个块包含512或4096字节。参见linux.die.net/man/8/blockdev
Cobra_Fast

6

您可以使用设置预读大小blockdev --setra sectors /dev/sda1,其中扇区是您想要的512字节扇区大小。


2

我的杀手设置非常简单而且非常有效:

echo "2000" > /proc/sys/vm/vfs_cache_pressure

内核文档中的解释:

vfs_cache_pressure

控制内核回收用于缓存目录和inode对象的内存的趋势。

在默认值vfs_cache_pressure = 100时,内核将尝试以相对于页面缓存和swapcache回收的“合理”速率回收牙科和索引节点。减小vfs_cache_pressure会导致内核倾向于保留dentry和inode缓存。当vfs_cache_pressure = 0时,内核将永远不会由于内存压力而回收内存和索引节点,这很容易导致内存不足的情况。将vfs_cache_pressure增加到100以上会导致内核更喜欢回收牙科和索引节点。

vfs_cache_pressure 在2000年,导致大多数计算发生在RAM中,并且磁盘写入非常晚。


4
设置vfs_cache_pressure得太高(我认为会2000太高)将导致不必要的磁盘访问,即使是简单的东西(例如目录列表)也应该很适合缓存。您拥有多少RAM,并且系统正在做什么?正如我在回答中所写的那样,对于此设置使用较高的值对于例如有限RAM的高清视频编辑是有意义的。
Mikko Rantalainen 2014年

2
请注意,参考文档继续:“将vfs_cache_pressure大大增加到100可能会对性能造成负面影响。回收代码需要采取各种锁定措施才能找到可释放的目录和inode对象。使用vfs_cache_pressure = 1000时,它将查找的可释放对象比此处多十倍。是。”
Mikko Rantalainen '18

1

与写缓存无关,但与写有关:

  • 对于ext4系统,您可以完全禁用日记功能

    这将减少任何特定更新的磁盘写入次数,但在意外关闭后可能需要使fsck或更糟,从而使文件系统处于不一致状态。

要阻止磁盘读取触发磁盘写入:

  • 使用relatimenoatime选项安装

    读取文件时,通常会更新该文件的“上次访问时间”元数据。该noatime选项将禁用该行为。这样可以减少不必要的磁盘写操作,但是您将不再拥有该元数据。一些发行版(例如,Manjaro)已将其作为所有分区上的默认设置(可能会延长早期型号SSD的寿命)。

    relatime根据帮助支持确实使用atime的应用程序的启发式方法,更新访问时间的频率降低了。这是Red Hat Enterprise Linux上的默认设置。

其他选项:

  • 在上面的评论中,Mikko分享了使用nobarrier选项进行安装的可能性。但是Ivailo 引用RedHat的警告。您多么想要这额外的3%?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.