在Linux上排队写入文件系统?

在Linux上排队写入文件系统?,linux,io,Linux,Io,在具有许多CPU的大型SMP机器上,脚本运行时同时执行数十个作业(少于CPU数量),如下所示: some_program -in FIFO1 >OUTPUT1 2>s_p1.log </dev/null & some_program -in FIFO2 >OUTPUT2 2>s_p2.log </dev/null & ... some_program -in FIFO40 >OUTPUT40 2>s_p40.log </dev

在具有许多CPU的大型SMP机器上,脚本运行时同时执行数十个作业(少于CPU数量),如下所示:

some_program -in FIFO1 >OUTPUT1 2>s_p1.log </dev/null &
some_program -in FIFO2 >OUTPUT2 2>s_p2.log </dev/null &
...
some_program -in FIFO40 >OUTPUT40 2>s_p40.log </dev/null &
splitter_program -in real_input.dat -out FIFO1,FIFO2...FIFO40
some_程序-在FIFO1>OUTPUT1 2>s_p1.log OUTPUT2>s_p2.log OUTPUT40 2>s_p40.log 80%)中,出现一个刷新进程(10%CPU),所有其他程序都降到低CPU(1%),然后返回到较高的速率。这些暂停一次持续几秒钟。刷新意味着写操作将压倒文件缓存。此外,我认为操作系统和/或底层RAID控制器可能会不稳定地反弹物理磁盘头,这会降低物理磁盘的最终写入速度。不过这只是一个猜测,因为很难说到底发生了什么,因为写入和磁盘之间有文件缓存(在一个内存超过500Gb的系统中)和RAID控制器

是否有一种程序或方法可以控制这种IO,强制文件系统写入很好地排队,以最大限度地提高写入速度

“buffer”程序在这里不会有多大帮助,因为它会将输出流累积成一大块,而不会有有序的写入队列,因此可能会有几个同时输出。如果输出流中的数据速率是不相关的,那么问题就不会那么严重,但在某些情况下,所有流中的数据速率完全相同,这意味着缓冲区将同时填满。这将使整个树暂停,直到最后一个树被写入,因为任何不能写入输出的进程都不会读取其下一个输入,这将使拆分器暂停,因为所有I/O都是同步的。缓冲区需要以循环的方式清空,最好是在任何缓冲区完全填满之前清空,尽管当数据输出速率超过文件系统写入速率时,这可能无法避免


有几十个参数用于优化文件系统,其中一些可能会有所帮助。调度程序从cfq更改为deadline,因为使用前者系统一次锁定数分钟。

如果问题是纯粹的I/O带宽,则缓冲无法解决任何问题。在这种情况下,您需要收缩数据或将其发送到更高带宽的接收器,以改进和提升性能。一种方法是减少并行工作的数量,正如@thatotherguy所说的那样

但是,如果事实上问题在于不同I/O操作的数量,而不是数据的总容量,那么缓冲可能是一个可行的解决方案。我不熟悉你提到的
buffer
程序,但我想它是按照它的名字来做的。然而,我并不完全同意你的缓冲意见:

“buffer”程序在这里不会有多大帮助,因为它会将输出流累积成一大块,而不会有有序的写入队列,因此可能会有几个同时输出

你不一定需要大块。以文件系统的本机块大小或其小整数倍进行分块可能是理想的。这可能是4096字节或8192字节的块

此外,我不明白为什么你认为你现在有一个“有序的写作队列”,或者为什么你相信这样的事情是必要的

如果输出流中的数据速率是不相关的,那么问题就不会那么严重,但在某些情况下,所有流中的数据速率完全相同,这意味着缓冲区将同时填满。这将使整个树暂停,直到最后一个树被写入,因为任何不能写入输出的进程都不会读取其下一个输入,这将使拆分器暂停,因为所有I/O都是同步的

您的拆分器正在写入FIFO。虽然它可以串行执行,但这不是“同步”的,因为在拆分器可以继续之前,数据需要从另一端排出——至少,如果写入不超过FIFO缓冲区的大小,就不需要。FIFO缓冲容量因系统而异,在某些系统上可动态调整,在某些系统上可配置(例如通过
fcntl()
)。现代Linux上的默认缓冲区大小为64kB

缓冲区需要以循环的方式清空,最好是在任何缓冲区完全填满之前清空,尽管当数据输出速率超过文件系统写入速率时,这可能无法避免

我认为这是一个几乎可以自行解决的问题。如果其中一个缓冲区的备份足以阻止拆分器,那么这将确保竞争进程在过长时间内为被阻止的缓冲区提供写入的机会。但这也是为什么您不需要巨大的缓冲区——您需要相对精细地将来自不同进程的磁盘I/O交错,以保持一切正常进行


外部缓冲程序的替代方案是修改进程以执行内部缓冲。这可能是一个优势,因为它从混合中删除了一整套管道(到外部缓冲程序),并且减轻了机器上的进程负载。不过,这确实意味着要修改您的工作处理程序,因此最好从外部缓冲开始,看看效果如何。

如果问题是40个流的数据速率都很高,并且RAID控制器无法足够快地写入物理磁盘,那么您需要重新设计磁盘系统。基本上,将其划分为40个RAID-1镜像,并向每个镜像集写入一个文件。这使得每个流的写入都是顺序的,但需要80个磁盘

如果数据速率不是问题所在,则需要添加更多缓冲。您可能需要一对线程。一个线程将数据收集到内存缓冲区中,另一个线程将数据写入数据文件并执行fsync()操作。要使磁盘写入连续,它应该一次对每个输出文件进行fsync。这将导致编写大量连续的whatev块