更一般而言,巨大的块大小(1 MB)可能大于RAID的块大小,因此I/O将在内核中拆分,而较小的部分将并行提交,因此足够大,以使您从缓冲写回中合并具有微小I/O的值(value)不高(
。此外,尽管RAID strip 大小可能大于1 MB,但内核对于硬件RAID并不总是知道这一点。对于软件RAID,内核可以有时会针对 strip 大小进行优化-例如,我所在的内核知道
鉴于以上所有情况,如果您在原始缓冲副本中将单个CPU用尽,并且您的工作量没有从缓存/销售中受益,但是磁盘可以处理更多的吞吐量,那么随着CPU时间的增加,
。我想象如果块大小很小(例如512字节),那将是一个非常不同的结果。
让我们比较一下fio的输出,以帮助我们理解这一点:
$ fio --bs=1M --size=20G --rw=write --filename=zeroes --name=buffered_1M_no_fsync
buffered_1M_no_fsync: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=2511MiB/s][r=0,w=2510 IOPS][eta 00m:00s]
buffered_1M_no_fsync: (groupid=0, jobs=1): err= 0: pid=25408: Sun Aug 25 09:10:31 2019
write: IOPS=2100, BW=2100MiB/s (2202MB/s)(20.0GiB/9752msec)
[...]
cpu : usr=2.08%, sys=97.72%, ctx=114, majf=0, minf=11
[...]
Disk stats (read/write):
md0: ios=0/3, merge=0/0, ticks=0/0, in_queue=0, util=0.00%, aggrios=0/0, aggrmerge=0/0, aggrticks=0/0, aggrin_queue=0, aggrutil=0.00%
因此,使用缓冲我们以大约2.1 GBytes/s的速度写入数据,但是用尽了整个CPU的时间。但是,块设备(md0
)表示几乎看不到任何I/O(ios=0/3
-只有三个写入I/O),这很可能意味着大部分I/O都缓存在RAM中!由于这台特定的机器可以轻松地在RAM中缓冲20 GB,因此我们将使用end_fsync=1
进行另一轮运行,以强制将可能只在运行结束时位于内核RAM缓存中的所有数据 push 磁盘,从而确保我们记录了时间使所有数据实际到达非 Volatile 存储:
$ fio --end_fsync=1 --bs=1M --size=20G --rw=write --filename=zeroes --name=buffered_1M
buffered_1M: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [F(1)][100.0%][r=0KiB/s,w=0KiB/s][r=0,w=0 IOPS][eta 00m:00s]
buffered_1M: (groupid=0, jobs=1): err= 0: pid=41884: Sun Aug 25 09:13:01 2019
write: IOPS=1928, BW=1929MiB/s (2023MB/s)(20.0GiB/10617msec)
[...]
cpu : usr=1.77%, sys=97.32%, ctx=132, majf=0, minf=11
[...]
Disk stats (read/write):
md0: ios=0/40967, merge=0/0, ticks=0/0, in_queue=0, util=0.00%, aggrios=0/2561, aggrmerge=0/2559, aggrticks=0/132223, aggrin_queue=127862, aggrutil=21.36%
好的,现在速度已降至约1.9 GBytes/s,我们仍然使用所有CPU,但RAID设备中的磁盘声称它们具有更快的容量(aggrutil=21.36%
)。下一步直接I/O:
$ fio --end_fsync=1 --bs=1M --size=20G --rw=write --filename=zeroes --direct=1 --name=direct_1M
direct_1M: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=3242MiB/s][r=0,w=3242 IOPS][eta 00m:00s]
direct_1M: (groupid=0, jobs=1): err= 0: pid=75226: Sun Aug 25 09:16:40 2019
write: IOPS=2252, BW=2252MiB/s (2361MB/s)(20.0GiB/9094msec)
[...]
cpu : usr=8.71%, sys=38.14%, ctx=20621, majf=0, minf=83
[...]
Disk stats (read/write):
md0: ios=0/40966, merge=0/0, ticks=0/0, in_queue=0, util=0.00%, aggrios=0/5120, aggrmerge=0/0, aggrticks=0/1283, aggrin_queue=1, aggrutil=0.09%
直接说来,我们使用不到50%的CPU来完成2.2 GB/s的速度(但是请注意,如何不合并I/O以及如何进行更多的用户空间/内核上下文切换)。如果我们要为每个系统调用增加更多的I/O,则情况将发生变化:
$ fio --bs=4M --size=20G --rw=write --filename=zeroes --name=buffered_4M_no_fsync
buffered_4M_no_fsync: (g=0): rw=write, bs=(R) 4096KiB-4096KiB, (W) 4096KiB-4096KiB, (T) 4096KiB-4096KiB, ioengine=psync, iodepth=1
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=2390MiB/s][r=0,w=597 IOPS][eta 00m:00s]
buffered_4M_no_fsync: (groupid=0, jobs=1): err= 0: pid=8029: Sun Aug 25 09:19:39 2019
write: IOPS=592, BW=2370MiB/s (2485MB/s)(20.0GiB/8641msec)
[...]
cpu : usr=3.83%, sys=96.19%, ctx=12, majf=0, minf=1048
[...]
Disk stats (read/write):
md0: ios=0/4667, merge=0/0, ticks=0/0, in_queue=0, util=0.00%, aggrios=0/292, aggrmerge=0/291, aggrticks=0/748, aggrin_queue=53, aggrutil=0.87%
$ fio --end_fsync=1 --bs=4M --size=20G --rw=write --filename=zeroes --direct=1 --name=direct_4M
direct_4M: (g=0): rw=write, bs=(R) 4096KiB-4096KiB, (W) 4096KiB-4096KiB, (T) 4096KiB-4096KiB, ioengine=psync, iodepth=1
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=5193MiB/s][r=0,w=1298 IOPS][eta 00m:00s]
direct_4M: (groupid=0, jobs=1): err= 0: pid=92097: Sun Aug 25 09:22:39 2019
write: IOPS=866, BW=3466MiB/s (3635MB/s)(20.0GiB/5908msec)
[...]
cpu : usr=10.02%, sys=44.03%, ctx=5233, majf=0, minf=12
[...]
Disk stats (read/write):
md0: ios=0/4667, merge=0/0, ticks=0/0, in_queue=0, util=0.00%, aggrios=0/292, aggrmerge=0/291, aggrticks=0/748, aggrin_queue=53, aggrutil=0.87%
由于块的大小为4 MB,缓冲的I/O成为“仅” 2.3 GBytes/s的瓶颈(即使当我们没有强制刷新高速缓存时),这是因为实际上没有CPU了。直接I/O使用了大约55%的CPU,并设法达到3.5 GB/s,因此它比缓冲I/O快大约50%。
简介:您的I/O模式并没有真正从缓冲中受益(I/O很大,数据没有被重用,I/O是按顺序流式传输的),因此您处于O_DIRECT
更快的最佳方案。有关其背后的原始动机,请参见这些slides by the original author of Linux's O_DIRECT
(更长的PDF document that contains an embedded version of most of the slides)。
我是一名优秀的程序员,十分优秀!