循环设备性能问题

循环设备性能问题

我正在尝试使用 dm-mapper,但它不接受文件。所以我需要一个设备。

所以我在ram(ramfs文件系统)的/dev/shm/f上创建了一个1500M的文件并将其映射到/dev/loop0(通过losetup)。

但与文件相比,我在循环设备上的性能约为第四。

ram 基准测试文件:

# dd if=/dev/shm/f of=/dev/null bs=16k 
96000+0 records in
96000+0 records out
1572864000 bytes (1.6 GB, 1.5 GiB) copied, 0.379551 s, 4.1 GB/s

环回设备基准:

# dd if=/dev/loop0 of=/dev/null bs=16k 
96000+0 records in
96000+0 records out
1572864000 bytes (1.6 GB, 1.5 GiB) copied, 1.62812 s, 966 MB/s

有没有更好的方法将文件写入设备?

如果没有,我可以做些什么来使循环设备更快?

编辑1: 系统规格:ram ddr2 667 和 CPU e5500

我尝试过创建 ramdisk 和 /dev/shm/f随机数据为了测试,将 bs=16k 更改为 bs=512k。听到结果:

  1. ramfs 上没有直接 io 的文件(不接受直接标志)3.5GB:
# dd if=/dev/shm/f of=/dev/null bs=512K status=progress 
2048+0 records in
2048+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.3091 s, 3.5 GB/s
  1. 不带和带直接 IO 的 ramdisk(1GB/s 和 3.4GB/s):
# dd if=/dev/ram0 of=/dev/null bs=512K status=progress 
937951232 bytes (938 MB, 894 MiB) copied, 1.00036 s, 938 MB/s
2048+0 records in
2048+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.22576 s, 876 MB/s
# dd if=/dev/ram0 of=/dev/null bs=512K status=progress iflag=direct
2048+0 records in
2048+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.319873 s, 3.4 GB/s

3)不带和带直接的循环设备(954MB/s 和 2.5GB/s):

# dd if=/dev/loop0 of=/dev/null bs=512k status=progress   
2048+0 records in
2048+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.1009 s, 975 MB/s
# dd if=/dev/loop0 of=/dev/null bs=512k status=progress iflag=direct
2048+0 records in
2048+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.436886 s, 2.5 GB/s
  1. 设备映射器中的 ramdisk(920MB/s 和 2.4GB/s)
mount /dev/mapper/ram-snap /mnt/sta1
cat /dev/urandom >/mnt/sta1/tst
# dd if=/mnt/sta1/tst of=/dev/null bs=512K count=1500 status=progress  conv=sync                 
1500+0 records in                                                                                                                                 
1500+0 records out
786432000 bytes (786 MB, 750 MiB) copied, 0.850705 s, 924 MB/s
# dd if=/mnt/sta1/tst of=/dev/null bs=512K count=1500 status=progress iflag=direct conv=sync
1500+0 records in
1500+0 records out
786432000 bytes (786 MB, 750 MiB) copied, 0.327174 s, 2.4 GB/s
  1. dm 上的循环设备,不带和带直接(950MB/s 和 1.7GB/s)
# dd if=/mnt/sta1/tst of=/dev/null bs=512K count=1500 status=progress 
1500+0 records in
1500+0 records out
786432000 bytes (786 MB, 750 MiB) copied, 0.827005 s, 951 MB/s
# dd if=/mnt/sta1/tst of=/dev/null bs=512k count=1500 status=progress iflag=direct 
1500+0 records in
1500+0 records out
786432000 bytes (786 MB, 750 MiB) copied, 0.451071 s, 1.7 GB/s

粗略地看,即使您可以使用直接标志,性能也会下降约 30%(情况 3、4 和 5),而在实际情况下,您无法控制直接标志,因此实际性能下降了 60% -70%(在我的系统上不直接读取的速度约为 800-1000 MB/s)。

考虑到某些SSD具有相同的读取速度,我认为有些问题。

有什么方法可以默认直接从循环设备(不是附加到循环设备的循环文件)读取?

答案1

将文件系统放入 RAM 中,只是为了在其上创建块设备支持文件,这是相当奇怪的……另外,ramfs 近年来不太受欢迎,取而代之的是更好的可调 tmpfs。我不认为有了内核大页支持,您应该会看到速度上的很大差异,但是,您的 ramfs 仍然相对较慢,通常,ramfs 比 tmpfs 快,而我的 tmpfs(在老式 DDR3 上!)相同的 bs 开箱即用 >6 GB/s。

不使用 ramfs/tmpfs,只需创建一个内存盘。您在这里找到的许多指令都有点旧 - 您可能需要也可能不需要brd内核模块来创建/dev/ram0可以直接使用的(或 ram1、2...)设备。我会推荐回答:

sudo modprobe brd rd_nr=1 rd_size=$((4 * 1048576))

另外,另一方面:16k 的尺寸对于这个来说确实很小。在 512k 或 1M 的块中工作可能会更快。 “但是,”你说,“这不明智,因为我的 dm 将使用 16k 块!”。

嗯,这是你可以通过你在 之上所做的事情来影响的md。此外,用户态速度在这里可能并不重要——复制的速度将很大程度上受到内核和用户态之间上下文切换数量的影响。

要预览您可以获得多快的速度,请尝试添加iflag=direct来自 ramdisk 的 dd 调用(并哭泣):

sudo dd if=/dev/ram0 of=/dev/null iflag=direct bs=16k
262144+0 records in
262144+0 records out
4294967296 bytes (4,3 GB, 4,0 GiB) copied, 0,457708 s, 9,4 GB/s
sudo dd if=/dev/ram0 of=/dev/null iflag=direct bs=1M
4096+0 records in
4096+0 records out
4294967296 bytes (4,3 GB, 4,0 GiB) copied, 0,220438 s, 19,5 GB/s

答案2

读取循环设备会产生开销,在对其进行基准测试时,尤其是在对内存速度进行基准测试时,这一点会很明显。如果您期望循环设备与直接传输一样快,那么这意味着内核不允许在内部多次复制数据,即使您正在通过多个抽象层,这可能涉及大量额外的系统调用。显然,内核实现还不够好。

除了常规开销之外,tmpfs 文件上的循环设备也可能产生副作用。因此,性能可能会很差,具体取决于文件的创建方式。

# truncate -s 1500M /dev/shm/f
# du /dev/shm/f
0   /dev/shm/f

创建文件truncate使其稀疏,因此它实际上不占用任何空间。

直接读取文件时没有任何变化:

# cat /dev/shm/f > /dev/null
# du /dev/shm/f
0   /dev/shm/f

然而,循环设备则不同:

# losetup --find --show /dev/shm/f
/dev/loop1
# cat /dev/loop1 > /dev/null
# du /dev/shm/f
1536000 /dev/shm/f

因此,读取循环设备会导致 tmpfs 文件被分配。这意味着 RAM 已为其分配,因此可能必须为其释放其他 RAM。如果存在交换空间,则该过程甚至可能涉及交换。

这是一种可能意想不到的副作用。

您可以尝试使用适当的 ramdisk 设备,而不是使用带有循环设备的 tmpfs,并希望它比文件循环的开销更少。

相关内容