性能测试用例和结果更新
This commit is contained in:
203
README.md
203
README.md
@@ -11,6 +11,35 @@ ZVFS 是一个 **透明用户态文件系统原型**,通过 `LD_PRELOAD` 劫
|
||||
|
||||
---
|
||||
|
||||
# 测试方案
|
||||
|
||||
```shell
|
||||
git clone http://gitlab.0voice.com/lianyiheng/zvfs.git
|
||||
cd zvfs
|
||||
git submodule update --init --recursive
|
||||
|
||||
cd spdk
|
||||
sudo ./scripts/pkgdep.sh
|
||||
sudo ./configure --with-shared
|
||||
sudo make -j
|
||||
sudo ./scripts/setup.sh
|
||||
|
||||
cd ..
|
||||
make && make test
|
||||
|
||||
su root
|
||||
|
||||
# 测试
|
||||
mkdir -p /zvfs/zvfs_sys_fio
|
||||
mkdir -p /tmp/zvfs_sys_fio
|
||||
|
||||
SPDK_JSON_CONFIG="$PWD/src/zvfsnvme.json" ./src/daemon/zvfs_daemon
|
||||
ZVFS_LD_PRELOAD_VALUE="$PWD/src/libzvfs.so" ./scripts/run_fio_matrix.sh
|
||||
|
||||
# 结果:
|
||||
results/fio/..../summary.md
|
||||
```
|
||||
|
||||
# 设计思路
|
||||
|
||||
大多数用户态文件系统(如 FUSE)需要修改应用或挂载文件系统。用户态文件系统如果要通过VFS,需要多一到两次额外的用户态/内核态切换。ZVFS 的目标是对应用完全透明:应用按正常方式调用 POSIX API,底层存储路径被悄悄替换掉。
|
||||
@@ -135,54 +164,89 @@ fcntl fcntl64 ioctl
|
||||
> 注:VMware 模拟 NVMe 无法体现 SPDK 轮询模式对中断驱动 I/O 的延迟优势,
|
||||
> 以下数据用于评估 hook 层与 IPC 的额外开销,不代表真实硬件上的性能对比。
|
||||
|
||||
### 顺序写吞吐
|
||||
### fio 4K(psync,30s)
|
||||
|
||||
| Block Size | spdk_nvme_perf | ZVFS |
|
||||
|---|---|---|
|
||||
| 4K | 100 MiB/s | 94 MiB/s |
|
||||
| 128K | 1843 MiB/s | 1662 MiB/s |
|
||||
测试口径:
|
||||
|
||||
ZVFS 达到 **SPDK 原生性能约 90%**。
|
||||
- `ioengine=psync`
|
||||
- `direct=1`
|
||||
- `iodepth=1`
|
||||
- `bs=4K`
|
||||
- `time_based=1`
|
||||
- `runtime=30`
|
||||
- `size=512M`
|
||||
- `sys`: 普通文件路径
|
||||
- `zvfs`: `LD_PRELOAD=./src/libzvfs.so`
|
||||
|
||||
---
|
||||
#### prepare_fill 顺序写带宽
|
||||
|
||||
### fio 随机写(16K,psync)
|
||||
| | sys | ZVFS |
|
||||
|---|---:|---:|
|
||||
| 带宽 | 10.92 MiB/s | 14.41 MiB/s |
|
||||
| disk util | 99.68% | 5.49% |
|
||||
|
||||
| | kernel (psync) | ZVFS |
|
||||
|---|---|---|
|
||||
| IOPS | 1855 | 1353 |
|
||||
| 吞吐 | 28.0 MiB/s | 21.2 MiB/s |
|
||||
| avg clat | 492 µs | 692 µs |
|
||||
| sys% | 28.6% | 8.4% |
|
||||
#### randread_4k
|
||||
|
||||
> 当前 ZVFS 在该单线程 `psync` 随机写场景下达到 kernel `psync` 的约 73% IOPS。daemon 内部 `SPDK + reply_q` 已收敛到较稳定范围,剩余主要开销集中在 `client -> daemon` 请求进入阶段。
|
||||
| | sys | ZVFS |
|
||||
|---|---:|---:|
|
||||
| IOPS | 3118.31 | 3685.21 |
|
||||
| 吞吐 | 12.18 MiB/s | 14.40 MiB/s |
|
||||
| avg clat | 318.31 µs | 268.91 µs |
|
||||
| disk util | 99.77% | 0.52% |
|
||||
|
||||
#### randwrite_4k
|
||||
|
||||
| | sys | ZVFS |
|
||||
|---|---:|---:|
|
||||
| IOPS | 2883.24 | 3816.78 |
|
||||
| 吞吐 | 11.26 MiB/s | 14.91 MiB/s |
|
||||
| avg clat | 344.20 µs | 259.53 µs |
|
||||
| disk util | 99.80% | 3.97% |
|
||||
|
||||
#### randrw_4k(50/50)
|
||||
|
||||
| | sys | ZVFS |
|
||||
|---|---:|---:|
|
||||
| 读 IOPS | 1614.29 | 2652.07 |
|
||||
| 写 IOPS | 1605.60 | 2637.78 |
|
||||
| 读 avg clat | 306.56 µs | 184.11 µs |
|
||||
| 写 avg clat | 309.72 µs | 189.44 µs |
|
||||
| disk util | 99.87% | 2.98% |
|
||||
|
||||
---
|
||||
|
||||
### WRITE 请求端到端延迟分解(单位 µs)
|
||||
基于 12 条 `WRITE` trace 样本统计,下面按调用栈层级展开平均耗时。由于四舍五入,父子项相加会有 `±1 µs` 误差。
|
||||
```bash
|
||||
sudo env \
|
||||
ZVFS_TRACE_LATENCY=1 \
|
||||
LD_PRELOAD="$PWD/src/libzvfs.so" \
|
||||
fio ./zvfs_fio_test/zvfs/randwrite_4k.fio 2> /tmp/zvfs.write.trace.log
|
||||
```
|
||||
基于 `/tmp/zvfs.write.trace.log` 中 `107946` 条 `WRITE` trace 样本统计,下面按调用栈层级展开平均耗时。由于四舍五入,父子项相加会有 `±1 µs` 误差。
|
||||
|
||||
```text
|
||||
total 748
|
||||
├─ c2s 317
|
||||
│ ├─ send 39
|
||||
│ └─ server_rx_wait 278
|
||||
├─ server 336
|
||||
│ ├─ rx_dispatch 12
|
||||
│ ├─ dispatch_spdk 25
|
||||
│ ├─ spdk 194
|
||||
│ └─ reply_q 103
|
||||
│ ├─ spdk_post 11
|
||||
│ └─ cq_wait 91
|
||||
│ ├─ kick 13
|
||||
│ ├─ wake_sched 65
|
||||
│ └─ wake_to_tx 12
|
||||
└─ s2c 95
|
||||
├─ resp_wait 83
|
||||
└─ parse 12
|
||||
total 256
|
||||
├─ c2s 41
|
||||
│ ├─ send 7
|
||||
│ └─ server_rx_wait 34
|
||||
├─ server 154
|
||||
│ ├─ rx_dispatch 0
|
||||
│ ├─ dispatch_spdk 5
|
||||
│ ├─ spdk 138
|
||||
│ │ ├─ phase1 0
|
||||
│ │ └─ phase2 138
|
||||
│ └─ reply_q 10
|
||||
│ ├─ spdk_post 0
|
||||
│ └─ cq_wait 10
|
||||
│ ├─ kick 1
|
||||
│ ├─ wake_sched 8
|
||||
│ └─ wake_to_tx 0
|
||||
└─ s2c 60
|
||||
├─ resp_wait 60
|
||||
└─ parse 0
|
||||
```
|
||||
|
||||
当前 `WRITE` 的主要额外开销已经比较清晰:一是 `c2s / server_rx_wait`,二是 `server` 内部的 `spdk` 与 `reply_q`。在 `reply_q` 中,`wake_sched` 已明显大于 `kick` 和 `wake_to_tx`,说明回包路径的主要损耗不在 `eventfd` 写入本身,而在 reactor 被唤醒后的调度等待。
|
||||
现在一次 `WRITE` 平均大约 `256 µs`。其中最耗时的是实际存储写入(`spdk`,约 `138 µs`),其次是请求发给 daemon 和结果返回应用这两段通信等待(`c2s` + `s2c`,约 `101 µs`)。回包队列相关开销(`reply_q`)已经压到约 `10 µs`,不再是主要瓶颈。
|
||||
|
||||
---
|
||||
|
||||
@@ -243,3 +307,74 @@ PostgreSQL tablespace 通过 symbolic link 访问路径: pg_tblspc/xxx
|
||||
## write 延迟显著高于预期
|
||||
|
||||
这次 fio 延迟排查里,最初 `WRITE` 延迟明显高于预期。沿端到端路径加轻量打点后发现问题并不在 SPDK 本体,而是同时叠加了无条件 RMW、VM 中 poller 调度抖动、线程未绑核,以及后期 trace 暴露出来的 reactor 唤醒后核心切换抖动。对应处理是:整块对齐写跳过 read phase、将 reactor/md/io 线程固定到指定 CPU,并把 io 线程数和绑核目标收敛到配置项中。修复后 `dispatch_spdk` 从毫秒级降到几十微秒,`WRITE` 平均延迟也回落到约 700 µs,但剩余尾延迟仍主要表现为请求进入与回包阶段的调度等待。
|
||||
|
||||
---
|
||||
|
||||
# 脚本参数
|
||||
|
||||
以下脚本都支持通过环境变量 `ZVFS_LD_PRELOAD_VALUE` 指定加载的 so 库:
|
||||
|
||||
- `scripts/run_fio_matrix.sh`
|
||||
- `scripts/run_pgbench_zvfs.sh`
|
||||
- `scripts/run_db_bench_zvfs.sh`
|
||||
- `scripts/run_test_hook_api.sh`
|
||||
|
||||
示例:
|
||||
|
||||
```bash
|
||||
sudo env ZVFS_LD_PRELOAD_VALUE="$PWD/src/libzvfs.so" ./scripts/run_fio_matrix.sh
|
||||
```
|
||||
|
||||
其他脚本同理:
|
||||
|
||||
```bash
|
||||
sudo env ZVFS_LD_PRELOAD_VALUE="$PWD/src/libzvfs.so" ./scripts/run_pgbench_zvfs.sh
|
||||
sudo env ZVFS_LD_PRELOAD_VALUE="$PWD/src/libzvfs.so" ./scripts/run_db_bench_zvfs.sh
|
||||
env ZVFS_LD_PRELOAD_VALUE="$PWD/src/libzvfs.so" ./scripts/run_test_hook_api.sh
|
||||
```
|
||||
|
||||
## 延迟 Trace
|
||||
|
||||
`WRITE` / `SYNC_MD` 的端到端阶段打印通过环境变量 `ZVFS_TRACE_LATENCY=1` 打开。
|
||||
打印代码在客户端侧 [`src/spdk_engine/io_engine.c`](/home/lian/share/zvfs/src/spdk_engine/io_engine.c),输出会写到执行 workload 的进程标准错误。
|
||||
|
||||
示例:
|
||||
|
||||
```bash
|
||||
sudo env \
|
||||
ZVFS_TRACE_LATENCY=1 \
|
||||
LD_PRELOAD="$PWD/src/libzvfs.so" \
|
||||
fio ./zvfs_fio_test/zvfs/randwrite_4k.fio 2> /tmp/zvfs.write.trace.log
|
||||
```
|
||||
|
||||
筛出 `WRITE` trace:
|
||||
|
||||
```bash
|
||||
grep '\[zvfs\]\[trace\]\[WRITE\]' /tmp/zvfs.write.trace.log
|
||||
```
|
||||
|
||||
筛出 `SYNC_MD` trace:
|
||||
|
||||
```bash
|
||||
grep '\[zvfs\]\[trace\]\[SYNC_MD\]' /tmp/zvfs.write.trace.log
|
||||
```
|
||||
|
||||
单行输出字段包括:
|
||||
|
||||
- `total`
|
||||
- `c2s`
|
||||
- `send`
|
||||
- `server_rx_wait`
|
||||
- `rx_dispatch`
|
||||
- `dispatch_spdk`
|
||||
- `spdk`
|
||||
- `phase1`
|
||||
- `phase2`
|
||||
- `spdk_post`
|
||||
- `kick`
|
||||
- `wake_sched`
|
||||
- `wake_to_tx`
|
||||
- `reply_q`
|
||||
- `cq_wait`
|
||||
|
||||
更新 README 中的 `WRITE 请求端到端延迟分解` 时,可对多条 `[zvfs][trace][WRITE]` 日志按字段取平均后再汇总。
|
||||
|
||||
Reference in New Issue
Block a user