python - 使用 Python 进行 NVMe 吞吐量测试

标签 python linux file-io nvme

目前我需要做一些吞吐量测试。我的硬件设置是我有一个三星 950 Pro 连接到一个 NVMe Controller ,该 Controller 通过 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

在/fsmnt/fs1 挂载 SSD 后,我使用这个 jobfile 来测试吞吐量

;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 使用 Linux 的缓冲区缓存(通过使用 buffered=0 这与说 direct=1 相同)告诉它做 O_DIRECT 操作。对于您指定的作业,fio 将必须发送一个 4k 写入,然后等待写入完成在设备上(并且该确认必须一直返回到 fio)之前可以发送下一个。

  • 您的 Python 脚本可以在接触您的 SSD 之前发送可以在多个级别缓冲的写入(例如,在用户空间中由 C 库缓冲,然后在内核的缓冲区缓存中再次缓冲)。这通常意味着写入将被累积并合并在一起,然后再被发送到较低级别,从而导致开销较小的 block 状 I/O。此外,由于理论上您没有进行任何显式刷新,因此在程序退出之前不必将 I/O 发送到磁盘(实际上这将取决于许多因素,例如您执行了多少 I/O,数量Linux 可以为缓冲区预留的 RAM、文件系统保存脏数据的最长时间、您执行 I/O 的时间等)!您的 os.close(write_file) 将变成 fclose() which says this in its Linux man page :

    Note that fclose() flushes only the user-space buffers provided by the C library. To ensure that the data is physically stored on disk the kernel buffers must be flushed too, for example, with sync(2) or fsync(2).

    事实上,您在调用 os.close() 之前花费了最后时间,因此您甚至可能忽略了将最后“批处理”数据仅发送到内核所花费的时间更不用说固态硬盘了!

您的 Python 脚本更接近这个 fio 作业:

[global]
ioengine=psync
rw=write
bs=4k
size=1g

[file1]
filename=/fsmnt/fio.tmp

即使使用此 fio 仍然处于劣势,因为您的 Python 程序具有用户空间缓冲(因此 bs=8k 可能更接近)。

关键要点是你的 Python 程序并没有真正测试你的 SSD 在你指定的 block 大小下的速度,你原来的 fio 作业有点奇怪,受到严格限制(libaio ioengine 是异步的,但有一个深度为 1 你将无法从中受益,那是在我们到达 behaviour of Linux AIO when using filesystems 之前,并且对你的 Python 程序做不同的事情。如果与最大缓冲区的大小相比,你没有做更多的缓冲 I/O(在 Linux 上,内核的缓冲区大小与 RAM 成比例)并且如果缓冲的 I/O 很小,那么练习就变成了有效性的演示缓冲。

关于python - 使用 Python 进行 NVMe 吞吐量测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48304612/

相关文章:

c++ - 链表中的段错误和 Linux 的调试选项

linux - 无法在自定义 Linux 上运行 mongod

java - 在写入完成之前拒绝对文件的读取访问 - java

java - 在文件输入输出java中使用数组列表

python - 从 python 脚本获取 jenkins 构建状态

python - Windows 10 上的 TensorFlow : “not a supported wheel on this platform” error

python - 来自 Pandas 数据框嵌套字典的 Pandas 数据框

Python:如何读取多个文件夹中的所有文本文件内容并将其保存到一个excel文件中

ruby - 在 Ubuntu 上从源代码安装 Ruby 1.9.3

c++ - 使用输入和输出选项读取文件流后无法写入