FIO 性能测试
本章包含两部分内容:一些规划及设计性能测试的建议,以及展示不同条件下性能测试的结果。如果你只想参考 JuiceFS 的性能测试结果,请下拉直接参考对应小节,不需要从头开始阅读。
明确测试意图、资源边界
JuiceFS 客户端可以跑到很高的吞吐(单个大文件读取 2GB/s 左右)——但前提是给足资源,并且使用性能极佳的对象存储服务。因此在文件系统测试开始前,需要明确目的:是希望不计成本给足资源、跑出极限性能呢,还是在接近实际生产资源隔离的条件下,看给定的资源能提供怎样的性能水平。
只有明确测试意图,后续测试成绩不达预期的时候,才能知道要怎么优化。如果你希望测试 JuiceFS 的极限性能,只要是资源引发的性能不足,都尽可能扩充资源、提升成绩。但是依照这种方式测得的极限性能,往往无法在实际环境中复现,因为生产资源不可能无限地分配给某个业务(或者 JuiceFS 客户端)。因此我们更推荐你「在接近实际生产资源隔离的条件下,看给定资源能提供怎样的性能水平」。本文中执行的测试,也都依照这个思路来设计。
测试对象存储(可选)
在一切开始之前,建议先验证对象存储的性能是否达到其宣称的规格。如果对存储后端的性能有着高预期,但实际测试时却发现吞吐不够,会陷入「不知道是 JuiceFS 没有做好调优、或是有 bug,还是对象存储本身性能不够」的困境。因此我们建议在测试前就确立好对象存储的实际性能水平,打好基础。
如果你在使用公有云提供的对象存储服务(S3、OSS 等),可以视情况跳过这道工序。但对于自建对象存储,或者采购了私有部署模式的商用对象存储,那么我们建议将对象存储测试作为必要项,并且在所有后续测试开始之前就验证好。
如果没有特殊需要,建议直接用 juicefs objbench 命令用来测试对象的性能,此处以 Ceph 为例,先测试单线程情况下的吞吐,确立基准:
# 记录 p=1 时的基准测试,获得最佳时延和单线程的带宽数据,用于后边的估算
juicefs objbench --storage=ceph --access-key=ceph --secret-key=client.jfspool jfspool -p=1 --big-object-size=4096
逐渐增大并发(-p),可以翻倍翻倍地测(最大到 CPU 核数),观察时延和带宽,前期应该是能够线性增长的。需要注意当并发较大时,如果预期带宽较大,需要增大 --big-object-size 来保证有足够的数据进行读写,获得准确的数据。例如:
juicefs objbench --storage=ceph --access-key=ceph --secret-key=client.jfspool jfspool -p 128 --big-object-size=4096
用递增并发的方式测得顶点以后,对于某些对象存储的 SDK,可能还需要增大 --object-clients,比方说 Ceph SDK 对单个客户端实例施加了带宽上限,因此用该参数增大客户端实例数,就能继续用更高的对象存储并发来提升吞吐,找到单机上限。例如:
juicefs objbench --storage=ceph --access-key=ceph --secret-key=client.jfspool jfspool -p 128 --big-object-size=4096 --object-clients=[2|3|4]
确认硬件信息(可选)
对于自建机房(数据中心),我们建议提前记录、核实机器的各项硬件规格,这是为了:
- 确认环境的正确性;
- 确认硬件性能符合预期。
CPU
记录 CPU 型号、个数、核数、频率相关的信息:
dmidecode -t processor | grep -E 'Socket Designation|Version|Speed|Core|Thread'
确认 CPU Governor。根据型号和驱动的不同,查询的地方会不同。简单的确认方式就是查看一下当前的运行频率:
cat /proc/cpuinfo | grep MHz
如果频率和标称相差比较大,建议和供应商沟通确认,确保性能模式等相关选项正确设置(比如采用“性能模式”),减少 CPU 频率波动对性能测试准确性的影响。
内存
记录类型、数量、大小、频率、NUMA 信息:
dmidecode --type memory | grep -E "Configured Memory Speed|Volatile Size|Type: DDR" | grep -vE "None|Unknown"
numactl --hardware
硬盘
硬盘对 JuiceFS 的缓存性能非常重要,尤其是分布式缓存场景,如果是自建机房,建议硬盘安装好以后,立刻对性能进行测试,确保达到标称。
以 NVMe 为例,可以使用 nvme-cli 来查看:
nvme list
用 FIO 对硬盘进行读写基准测试,下方的测试实例会给出 4K 随机读写的 IOPS 和 1M 大小时的吞吐。
fio --name=4k --filename=/dev/nvme0n1 --ioengine=libaio --direct=1 --iodepth=128 --bs=4K --rw=randwrite --numjobs=16 --group_reporting
fio --name=4k --filename=/dev/nvme0n1 --ioengine=libaio --direct=1 --iodepth=128 --bs=4K --rw=randread --numjobs=16 --group_reporting
fio --name=1m --filename=/dev/nvme0n1 --ioengine=libaio --direct=1 --iodepth=128 --bs=1M --rw=write --numjobs=16 --group_reporting
fio --name=1m --filename=/dev/nvme0n1 --ioengine=libaio --direct=1 --iodepth=128 --bs=1M --rw=read --numjobs=16 --group_reporting
将测试结果和该硬盘型号对应的标称性能数据进行对比,确认是否符合预期。如果确实出现性能不符的情况,除了硬盘本身的故障外,也有可能不慎将本该使用 NVMe 协议的硬盘插错接口(比如 SATA AHCI 协议)导致性能下降的情况,建议与机房运维一起协查。
网卡
- 首先记录网卡信息,根据预先规划的网段找一下对应的网卡,运行
ethtool <interface>确认其带宽。如果该网卡是 bond,那么cat /proc/net/bonding/<interface>来记录 bond 信息,了解 slave 是谁、哈希策略等; - 网卡速率可能受到 CPU 等因素的影响,在没有其他网络负载的前提下,用 iperf 进行压测并记录结果;
- 测试期间额外核实确认路由是否正确,例如通过
sar -n DEV 1来确认网卡的流量状况,判断是否流量走在正确的网卡,bond 网卡是否流量均衡; - 如需测试独立缓存集群场景,需要确认清楚:缓存提供方和消费端分别位于哪些机器,这些机器是否同属一个网络环境?如果需要跨 VPC 或者其他涉及到跨网络环境访问,建议提前测试好跨网络环境的性能,谨防网络环境引起的性能下降。