在用perf工具测试SPDK NVMe驱动是时候,有如下的命令
perf -q 128 -o 4096 -w randread -r 'trtype:PCIe traddr:0000:04:00.0' -t 300
这是使用 perf 对本地 NVMe SSD 进行 4K 100% 随机读取工作负载 300 秒,
q参数是队列深度,o参数是io读取大小,这里读取4K大小,w参数是io语法,一共有(read, write, randread, randwrite, rw, randrw)6种,r参数是传输的id
更多关于spdk的perf参数,请执行下面的语句查询
vagrant@vagrant:~/spdk$ ./build/examples/perf --help
SO,队列深度的指定,对程序有什么影响吗?
SPDK官网NVMe Driver 给出的说法是
NVMe 队列对 (struct spdk_nvme_qpair) 为 I/O 提供并行提交路径。I/O 可以从不同的线程同时提交到多个队列对上。允许的队列对数量由 NVMe SSD 本身决定。
后面找到这段资料说的挺好,分享给大家,
来自英特尔亚太研发有限公司.《Linux开源存储全栈详解:从Ceph 到容器存储》.[Z].北京.电子工业出版社.2019.
在设计通用块层的数据流的时候,需要考虑后端不同设备的特性,比如某些设备可以支持很高的并发量,某些设备无法支持单个I/O的终止操作(Abort),对数据流上的考虑大致包括以下内容。
- 引入I/O队列来缓存从上层模块接收到的I/O请求,而不是直接传递给下层。这样不同的后端设备都可以按照不同的速率来完成这些I/O请求。同时基于这个I/O队列还能起到一些额外的作用,比如限速流控、不同优先级处理、I/O分发等。当后端设备遇到一些异常情况时,比如当Buffer资源不够时,这个I/O队列也可以重新把这些发下去的I/O请求再次进入队列做第二次读/写尝试。
- 引入通用的异常恢复机制。比如某个I/O请求可能在下层具体设备停留过久导致的超时问题;比如设备遇到严重问题导致无法响应而需要设备重置;比如设备的热插拔导致的I/O请求的出错处理。与其让每一个下层具体设备都来实现这些异常恢复机制,不如在通用块层就来进行处理。