sysbench 是一个非常经典的综合性能测试工具, 通常都用它来做数据库的性能压测, 但也可以用来做 CPU,IO 的性能测试. 而对于 IO 测试, 不是很推荐 sysbench, 倒不是说它有错误, 工具本身没有任何问题, 它的测试方法导致测试的数据会让人有些困惑: 性能数据到底是不是这样呢, 跟云厂商承诺的性能有关系嘛. 一般我们都用 FIO 来进行性能测试, 云厂商都推荐用 FIO 进行性能测试, 通过 FIO 性能测试, 都能轻易达到云厂商承诺的性能.
插曲: 关于 sysbench 的版本, 现在主要有 0.4.12 和 1.0. 版本. 截止 2006 年 sysbench 好长时间没有发展, 2017 年之前都是用旧版本 0.4.12(所以网上一搜一大堆文章都是 0.4. 的教程), 然后作者估计修了几个 bug, 变成 0.5 版本, 然后就跟过去做了告别, 从 2017 重新开发了一个新版本 sysbench 1.0.*, 这里讲述的性能测试都是用了最新版.
1. sysbench fileio 测试
言归正传, sysbench 怎么做 IO 的性能测试呢, sysbench fileio help, 参数如下:
- #/usr/local/sysbench_1/bin/sysbench fileio help
- sysbench 1.0.9 (using bundled LuaJIT 2.1.0-beta2)
- fileio options:
- --file-num=N number of files to create [128]
- --file-block-size=N block size to use in all IO operations [16384]
- --file-total-size=SIZE total size of files to create [2G]
- --file-test-mode=STRING test mode {seqwr, seqrewr, seqrd, rndrd, rndwr, rndrw}
- --file-io-mode=STRING file operations mode {sync,async,mmap} [sync]
- --file-async-backlog=N number of asynchronous operatons to queue per thread [128]
- --file-extra-flags=STRING additional flags to use on opening files {sync,dsync,direct} []
- --file-fsync-freq=N do fsync() after this number of requests (0 - don't use fsync()) [100]
- --file-fsync-all[=on|off] do fsync() after each write operation [off]
- --file-fsync-end[=on|off] do fsync() at the end of test [on]
- --file-fsync-mode=STRING which method to use for synchronization {fsync, fdatasync} [fsync]
- --file-merged-requests=N merge at most this number of IO requests if possible (0 - don't merge) [0]
- --file-rw-ratio=N reads/writes ratio for combined test [1.5]
sysbench 的性能测试都需要做 prepare,run,cleanup 这三步, 准备数据, 跑测试, 删除数据. 那下面就开始实战:
客户用 2C4G 的 vm, 挂载 120G 的 SSD 云盘做了性能测试, 测试命令如下:
- cd /mnt/vdb #一定要到你测试的磁盘目录下执行, 否则可能测试系统盘了
- sysbench fileio --file-total-size=15G --file-test-mode=rndrw --time=300 --max-requests=0 prepare
- sysbench fileio --file-total-size=15G --file-test-mode=rndrw --time=300 --max-requests=0 run
- sysbench fileio --file-total-size=15G --file-test-mode=rndrw --time=300 --max-requests=0 cleanup
结果如下:
- File operations:
- reads/s: 2183.76
- writes/s: 1455.84
- fsyncs/s: 4658.67
- Throughput:
- read, MiB/s: 34.12
- written, MiB/s: 22.75
- General statistics:
- total time: 300.0030s
- total number of events: 2489528
- Latency (ms):
- min: 0.00
- avg: 0.12
- max: 204.04
- 95th percentile: 0.35
- sum: 298857.30
- Threads fairness:
- events (avg/stddev): 2489528.0000/0.00
- execution time (avg/stddev): 298.8573/0.00
随机读写性能好像不咋地, 换算 IOPS 为 (34.12+22.75)*1024/16.384=3554.375, 与宣称的 5400IOPS 有很大差距. 眼尖的人肯定发现只有 2 个核, 去遍历 128 个文件, 好像会降低效率, 于是定制 file-num 去做了系列测试, 测试结果如下:
file-num | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 |
---|---|---|---|---|---|---|---|---|
read(MB/s) | 57.51 | 57.3 | 57.36 | 57.33 | 55.12 | 47.72 | 41.11 | 34.12 |
write(MB/s) | 38.34 | 38.2 | 38.24 | 38.22 | 36.75 | 31.81 | 27.4 | 22.75 |
明显可以看到, 默认测试方法会导致性能下降, 文件数设置为 1 达到最大性能.
那 file-num=128 与 file-num=1 的区别是测试文件从 128 个变成 1 个, 但是总文件大小都是 15G, 都是随机读写, 按理性能应该是一致的, 区别是会在多个文件之间切换读写, 那么可能会导致中断增加和上下文切换开销增大. 通过 vmstat 命令得到了验证:
file-num=128 的 vmstat 输出是这样的:
file-num=1 的 vmstat 输出是这样的:
从上面两个图可以看出 file-num=1 的时候上下文切换只有 8500 左右比 file-num=128 的时候 24800 小多了, in(中断) 也少太多了. 减少了中断和上下文切换开销, 吞吐能力显著提升了.
再做了一个实验, 同样磁盘大小, 改成挂载到 8C 的 vm 下, 改成 8 线程进行测试, 得到如下数据:
file-num | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 |
---|---|---|---|---|---|---|---|---|
read(MB/s) | 253.08 | 209.86 | 193.38 | 159.73 | 117.98 | 86.78 | 67.39 | 51.98 |
write(MB/s) | 168.72 | 139.9 | 128.92 | 106.49 | 78.66 | 57.85 | 44.93 | 34.65 |
可以得出同样的结论, file-num=1 可以得到最好的性能, 理由如上.
2. 与 fio 测试的比较
单进程下, file-num=1 换算到 IOPS 为 (57.51+38.34)*1024/16.384=5990.625, 这好像超过我们的 IOPS 设置限定了. 通过 fio 是怎么测得这个 IOPS 的呢:
fio -direct=1 -iodepth=128 -rw=randrw -ioengine=libaio -bs=4k -size=1G -numjobs=1 -runtime=1000 -group_reporting -filename=iotest -name=randrw_test
通过阅读源代码, 发现很多不同:
一个是通过 libaio, 一个是通过 pwrite/pread.libaio 的性能是非常强劲的, 详情可以参考文章.
即使 ioengine=psync, 这个 engine 的读写方法是 pread 和 pwrite, 但是整个实现也是不一致的.
fio 测试的时候 direct=1, 就是每次都写入磁盘, 而 sysbench 默认 file-fsync-freq=100, 也就是完成 100 次操作才会有一个 fsync 操作, 这种操作涉及系统缓存.
3. 深入一步
上节认为操作系统干扰以及 io 读写方式的差异, 造成了测试数据的不一致. 深入去研究了下源代码, 其实 sysbench 的作者是提倡用 libaio, 代码里面大量地运用了宏定义, 如:
- /* 异步写的截取代码 */
- #ifdef HAVE_LIBAIO
- else if (file_io_mode == FILE_IO_MODE_ASYNC)
- {
- /* Use asynchronous write */
- io_prep_pwrite(&iocb, fd, buf, count, offset);
- if (file_submit_or_wait(&iocb, FILE_OP_TYPE_WRITE, count, thread_id))
- return 0;
- return count;
- }
- #endif
那怎么启用这个宏呢, 默认就是启用这个宏的.
启用这个宏后, 执行 sysbench fileio help, 会发现有这一项:--file-async-backlog=N number of asynchronous operatons to queue per thread [128], 说明 HAVE_LIBAIO 这个宏确实生效了.
既然 sysbench 默认有 libaio 后, 那整个测试方法需要调整:
- # --file-extra-flags=direct 文件读写模式改成 direct
- # --file-io-mode=async 确保 libaio 起效
- # --file-fsync-freq=0 不需要执行 fsync
- sysbench fileio --file-total-size=15G --file-test-mode=rndrw --time=300 --max-requests=0 --file-io-mode=async --file-extra-flags=direct --file-num=1 --file-rw-ratio=1 --file-fsync-freq=0 run
得到测试结果如下:
对于 FIO 命令也进行了调整, 把 bs 调整成 16k, 其他不变, 还是达到上限 5400. 测试结果如下:
可以看到 sysbench 测试的效果与 fio 的测试效果完全一致!
不过个人还是推荐 FIO 来做 IO 的性能测试.
原文链接 https://yq.aliyun.com/articles/680017
来源: https://www.cnblogs.com/yunqishequ/p/10156394.html