繁体   English   中英

使用Python的NVMe吞吐量测试

[英]NVMe Throughput Testing with Python

目前,我需要进行一些吞吐量测试。 我的硬件设置是将Samsung 950 Pro连接到NVMe控制器,该控制器通过和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之后,我使用此作业文件来测试吞吐量

;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程序比您的工作做得更好的原因是,这不是一个公平的比较,他们正在测试不同的东西:

  • 您通过告诉Linux进行O_DIRECT操作来禁止使用Linux的缓冲区高速缓存(通过使用buffered=0 ,它与direct=1相同)。 使用您指定的作业,fio将必须发送单个4k写入,然后等待该写入在设备上完成(并且确认必须完全返回到fio),然后才能发送下一个。

  • 允许您的Python脚本发送可在多个级别上进行缓冲的写入操作(例如,通过C库在用户空间内,然后在内核的缓冲区高速缓存中),然后再触摸SSD。 这通常意味着写入将被累积并合并在一起,然后再向下发送到较低级别,从而导致块化I / O的开销更少。 此外,由于理论上您无需进行任何显式刷新,因此无需在程序退出之前将I / O发送到磁盘(实际上,这取决于许多因素,例如您执行的I / O数量,数量的内存Linux可以留出缓冲区,文件系统将保留脏数据的最长时间,为I / O做多长时间等)! 您的os.close(write_file)会变成一个fclose() ,在Linux手册页中这样说

    请注意,fclose()仅刷新C库提供的用户空间缓冲区。 为了确保将数据物理存储在磁盘上,内核缓冲区也必须进行刷新,例如,使用sync(2)或fsync(2)。

    实际上,您在调用os.close()之前花了最后的时间,因此您甚至os.close()将最终的“批处理”数据仅发送到内核(更不用说SSD了)所花费的时间!

您的Python脚本更接近此任务:

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

[file1]
filename=/fsmnt/fio.tmp

即使这样,由于您的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的Pynvme是Python扩展。 您可以使用其ioworker()编写性能测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM