目前我需要做一些吞吐量测试。我的硬件设置是,我有一个连接到 NVMe 控制器的 Samsung 950 Pro,该控制器通过 PCIe 端口连接到主板。我有一个 Linux nvme 设备,与我在文件系统上的某个位置安装的设备相对应。
我的希望是使用Python来做到这一点。我计划在安装 SSD 的文件系统上打开一个文件,记录时间,将一些 n 长度的字节流写入文件,记录时间,然后使用 os 模块文件操作实用程序关闭文件。这是衡量写入吞吐量的函数。
def perform_timed_write(num_bytes, blocksize, fd):
"""
This function writes to file and records the time
The function has three steps. The first is to write, the second is to
record time, and the third is to calculate the rate.
Parameters
----------
num_bytes: int
blocksize that needs to be written to the file
fd: string
location on filesystem to write to
Returns
-------
bytes_per_second: float
rate of transfer
"""
# generate random string
random_byte_string = os.urandom(blocksize)
# open the file
write_file = os.open(fd, os.O_CREAT | os.O_WRONLY | os.O_NONBLOCK)
# set time, write, record time
bytes_written = 0
before_write = time.clock()
while bytes_written < num_bytes:
os.write(write_file, random_byte_string)
bytes_written += blocksize
after_write = time.clock()
#close the file
os.close(write_file)
# calculate elapsed time
elapsed_time = after_write - before_write
# calculate bytes per second
bytes_per_second = num_bytes / elapsed_time
return bytes_per_second
我的另一种测试方法是使用 Linux fio 实用程序。 https://linux.die.net/man/1/fio
将 SSD 安装在 /fsmnt/fs1 后,我使用此作业文件来测试吞吐量
;Write to 1 file on partition
[global]
ioengine=libaio
buffered=0
rw=write
bs=4k
size=1g
openfiles=1
[file1]
directory=/fsmnt/fs1
我注意到Python函数返回的写入速度明显高于fio。因为 Python 是如此高级,所以你放弃了很多控制权。我想知道 Python 是否在幕后做一些事情来欺骗它的速度。有谁知道为什么 Python 生成的写入速度比 fio 生成的写入速度高得多?
你的 Python 程序比你的 fio 工作做得更好的原因是因为这不是一个公平的比较,而且他们正在测试不同的东西:
您通过告诉 fio 执行
buffered=0
操作来禁止 fio 使用 Linux 的缓冲区缓存(通过使用 direct=1
,与说 O_DIRECT
相同)。对于您指定的作业,fio 将必须发送单个 4k 写入,然后等待该写入在设备上完成(并且该确认必须一路返回到 fio),然后才能发送下一个。
os.close(write_file)
将变成
fclose()
,在其 Linux 手册页中这样说:请注意,fclose() 仅刷新 C 库提供的用户空间缓冲区。为了确保数据物理存储在磁盘上,内核缓冲区也必须刷新,例如使用sync(2)或fsync(2)。
之前花费了最后的时间,因此您甚至可能忽略了仅将最后“批次”数据发送到内核所花费的时间,更不用说 SSD 了! 你的Python脚本更接近这个fio工作:事实上,您在调用
os.close()
[global]
ioengine=psync
rw=write
bs=4k
size=1g
[file1]
filename=/fsmnt/fio.tmp
即使有了这个 fio 仍然处于劣势,因为你的 Python 程序有用户空间缓冲(所以
bs=8k
可能更接近)。
关键的一点是你的Python程序并没有真正测试你的SSD在指定块大小下的速度,而且你原来的fio工作有点奇怪,受到严格限制(
libaio
ioengine是异步的,但深度为1,你不是能够从中受益,这是在我们了解 Linux AIO 使用文件系统时的行为
)并对 Python 程序执行不同的操作之前。如果与最大缓冲区的大小相比,您没有执行更多的缓冲 I/O(并且在 Linux 上,内核的缓冲区大小随 RAM 缩放),并且如果缓冲 I/O 很小,则练习将变成有效性的演示缓冲。如果您需要NVMe设备的精确性能,fio是最佳选择。 FIO可以直接将测试数据写入设备,无需任何文件系统。这是一个例子:
[global]
ioengine=libaio
invalidate=1
iodepth=32
time_based
direct=1
filename=/dev/nvme0n1
[write-nvme]
stonewall
bs=128K
rw=write
numjobs=1
runtime=10000
SPDK是另一种选择。
https://github.com/spdk/spdk/tree/master/examples/nvme/perf有一个现有的性能测试示例。 是基于SPDK的Python扩展。您可以使用其 ioworker() 编写性能测试。 您可以使用 NVMe SSD 测试工具 Penetrate (