在一个具有许多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
分离器会读取输入数据并按顺序将其分配到FIFO中。(记录1、41、81...分配到FIFO1;2、42、82分配到FIFO2等)。分离器的开销较低,可以几乎以文件系统提供数据的速度处理数据。
每个some_program处理其流并将其写入其输出文件。然而,没有控制文件系统看到这些写入的顺序。这些写入也非常小,大约10个字节。脚本“知道”这里有40个流,它们可以在20M(或其他)块中缓冲,然后将每个块顺序写入文件系统。也就是说,应该使用排队写入来最大化磁盘的写入速度。然而,操作系统只看到40个流中的每一个以大约相同的速率进行写入。
实际运行时发生的情况是,子进程获得很多CPU时间(在top中>80%),然后出现了一个刷新进程(10% CPU),所有其他进程的CPU都降到了很低(1%),然后又回到了更高的速率。这些暂停持续几秒钟。刷新意味着写入超过了文件缓存。此外,我认为操作系统和/或底层RAID控制器可能会使物理磁头不规则地反弹,从而降低了最终写入物理磁盘的速度。不过这只是一个猜测,因为很难说到底发生了什么,因为在写入和磁盘之间有文件缓存(在一个具有超过500Gb RAM的系统中)和RAID控制器。
是否有程序或方法可以控制这种IO,强制文件系统写入排队以最大化写入速度?
“缓冲”程序在这里帮助不大,因为虽然它会将输出流累积成一个大块,但不会有有序的写入排队,因此几个写入可能会同时进行。如果输出流中的数据速率不相关,这将是较小的问题,但在某些情况下,所有流的数据速率都完全相同,这意味着缓冲区将同时填满。这将使整个树停止,直到最后一个被写入,因为任何无法写出输出的进程都不会读取其下一个输入,这将使分离器停止,因为所有I/O都是同步的。最好在任何一个缓冲区完全填满之前就循环地清空缓冲区,尽管当数据输出速率超过文件系统写入速率时,这可能是不可避免的。
有数十个调整文件系统的参数,其中一些可能有所帮助。调度程序从cfq更改为deadline,因为前者会导致系统锁定数分钟。