mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-17 10:17:55 +00:00
96b1f5c373
* feat(storage): tune gt1g get read path * docs(ops): add gt1g get benchmark guide * feat(scripts): add gt1g get fallback runner * test(storage): trim gt1g get helper warnings * test(storage): reduce gt1g get helper type complexity
259 lines
5.9 KiB
Markdown
259 lines
5.9 KiB
Markdown
# Issue #713 `>1GiB GET` 优化与验证手册
|
||
|
||
## 1. 目标
|
||
|
||
本文用于收口 `backlog#713` 当前这一轮 `>1GiB GET` 优化的实现点与验证方式。
|
||
|
||
当前这轮改动先解决三件事:
|
||
|
||
1. `sequential hint` 真正参与 GET I/O 策略计算
|
||
2. storage media buffer cap 不再被统一的 `1MiB` hard clamp 二次截断
|
||
3. `>1GiB`、非 range、允许 readahead 的 streaming GET,会走更大的 stream buffer 策略
|
||
|
||
## 2. 当前代码行为变化
|
||
|
||
### 2.1 多因素调度
|
||
|
||
涉及:
|
||
|
||
1. `rustfs/src/storage/concurrency/io_schedule.rs`
|
||
|
||
当前行为:
|
||
|
||
1. `IoSchedulingContext.is_sequential_hint=true` 时,会优先按 `Sequential` 模式参与 buffer / readahead 决策
|
||
2. storage profile 提供的 media cap 现在可以真实生效
|
||
3. 例如默认常量下:
|
||
- `NVMe`: `2MiB`
|
||
- `SSD`: `1MiB`
|
||
- `HDD`: `512KiB`
|
||
|
||
### 2.2 GET body stream 策略
|
||
|
||
涉及:
|
||
|
||
1. `rustfs/src/app/object_usecase.rs`
|
||
|
||
当前行为:
|
||
|
||
1. `optimal_buffer_size` 不再被额外 `min(base_buffer_size)` 压回去
|
||
2. `>1GiB`、非 range、`enable_readahead=true` 的 streaming GET,会命中:
|
||
- `large_sequential_readahead`
|
||
3. 该路径当前把 `ReaderStream` buffer 扩到:
|
||
- `min(optimal_buffer_size * 2, 4MiB)`
|
||
|
||
### 2.3 GET observability
|
||
|
||
涉及:
|
||
|
||
1. `crates/io-metrics/src/lib.rs`
|
||
|
||
新增:
|
||
|
||
1. `rustfs_io_get_object_stream_strategy_total{strategy=...}`
|
||
2. `rustfs_io_get_object_stream_buffer_size_bytes{strategy=...}`
|
||
3. `rustfs_io_get_object_stream_response_size_bytes{strategy=...}`
|
||
|
||
当前策略标签:
|
||
|
||
1. `standard`
|
||
2. `large_sequential_readahead`
|
||
|
||
## 3. 推荐验证顺序
|
||
|
||
按下面顺序做最稳妥:
|
||
|
||
1. 先准备 plain `1GiB` / `2GiB` 对象
|
||
2. 先跑 `sequential` baseline
|
||
3. 再跑 `ranged_parallel`
|
||
4. 最后再决定是否继续补 encrypted / compressed
|
||
|
||
## 4. 准备测试对象
|
||
|
||
直接使用:
|
||
|
||
1. `scripts/prepare_gt1g_get_test_objects.sh`
|
||
|
||
示例:
|
||
|
||
```bash
|
||
bash scripts/prepare_gt1g_get_test_objects.sh \
|
||
--endpoint http://127.0.0.1:9000 \
|
||
--access-key rustfsadmin \
|
||
--secret-key rustfsadmin \
|
||
--bucket rustfs-bench \
|
||
--prefix bench/issue713/plain
|
||
```
|
||
|
||
默认会准备:
|
||
|
||
1. `1GiB=plain-1g.bin`
|
||
2. `2GiB=plain-2g.bin`
|
||
|
||
默认最终对象路径:
|
||
|
||
1. `s3://rustfs-bench/bench/issue713/plain/plain-1g.bin`
|
||
2. `s3://rustfs-bench/bench/issue713/plain/plain-2g.bin`
|
||
|
||
## 5. 执行 GET 矩阵
|
||
|
||
直接使用:
|
||
|
||
1. `scripts/run_gt1g_get_http_matrix.sh`
|
||
|
||
这个脚本特点:
|
||
|
||
1. 不把响应体落到本地磁盘
|
||
2. 直接把 body 丢到 `/dev/null`
|
||
3. 用 `curl` 的 `size_download` 做字节校验和吞吐计算
|
||
4. 同时支持:
|
||
- `sequential`
|
||
- `ranged_parallel`
|
||
|
||
补充说明:
|
||
|
||
1. 如果本机没有 `mc`,脚本会自动 fallback 到仓库内置的 `rustfs/tests/gt1g_get_benchmark_tool.rs`
|
||
2. fallback 模式下,结果目录会落在:
|
||
- `rustfs/target/bench/...`
|
||
3. 非 fallback 模式下,结果目录仍按脚本参数落在:
|
||
- `target/bench/...`
|
||
|
||
### 5.1 baseline:sequential + ranged_parallel
|
||
|
||
```bash
|
||
bash scripts/run_gt1g_get_http_matrix.sh \
|
||
--endpoint http://127.0.0.1:9000 \
|
||
--access-key rustfsadmin \
|
||
--secret-key rustfsadmin \
|
||
--bucket rustfs-bench \
|
||
--objects '1GiB=bench/issue713/plain/plain-1g.bin,2GiB=bench/issue713/plain/plain-2g.bin' \
|
||
--modes sequential,ranged_parallel \
|
||
--concurrencies 1,4,8 \
|
||
--range-workers 4 \
|
||
--rounds 3 \
|
||
--cooldown-secs 20
|
||
```
|
||
|
||
### 5.2 只跑 sequential
|
||
|
||
```bash
|
||
bash scripts/run_gt1g_get_http_matrix.sh \
|
||
--endpoint http://127.0.0.1:9000 \
|
||
--access-key rustfsadmin \
|
||
--secret-key rustfsadmin \
|
||
--bucket rustfs-bench \
|
||
--objects '1GiB=bench/issue713/plain/plain-1g.bin,2GiB=bench/issue713/plain/plain-2g.bin' \
|
||
--modes sequential \
|
||
--concurrencies 1,4,8 \
|
||
--rounds 3 \
|
||
--cooldown-secs 20
|
||
```
|
||
|
||
### 5.3 只跑 ranged_parallel
|
||
|
||
```bash
|
||
bash scripts/run_gt1g_get_http_matrix.sh \
|
||
--endpoint http://127.0.0.1:9000 \
|
||
--access-key rustfsadmin \
|
||
--secret-key rustfsadmin \
|
||
--bucket rustfs-bench \
|
||
--objects '1GiB=bench/issue713/plain/plain-1g.bin,2GiB=bench/issue713/plain/plain-2g.bin' \
|
||
--modes ranged_parallel \
|
||
--concurrencies 1,4,8 \
|
||
--range-workers 4,8 \
|
||
--rounds 3 \
|
||
--cooldown-secs 20
|
||
```
|
||
|
||
## 6. 输出目录
|
||
|
||
默认输出:
|
||
|
||
```text
|
||
target/bench/gt1g-get-http-<timestamp>/
|
||
```
|
||
|
||
重点看:
|
||
|
||
1. `round_results.csv`
|
||
2. `median_summary.csv`
|
||
3. `logs/`
|
||
|
||
`round_results.csv` 字段:
|
||
|
||
1. `object_label`
|
||
2. `object_key`
|
||
3. `mode`
|
||
4. `range_workers`
|
||
5. `concurrency`
|
||
6. `round`
|
||
7. `status`
|
||
8. `total_bytes`
|
||
9. `elapsed_ms`
|
||
10. `throughput_bps`
|
||
11. `avg_client_latency_ms`
|
||
|
||
## 7. 当前推荐观察点
|
||
|
||
### 7.1 sequential 是否命中大对象策略
|
||
|
||
查询:
|
||
|
||
```promql
|
||
sum by (strategy) (
|
||
increase(rustfs_io_get_object_stream_strategy_total[5m])
|
||
)
|
||
```
|
||
|
||
预期:
|
||
|
||
1. `>1GiB` 顺序 GET 应出现 `large_sequential_readahead`
|
||
|
||
### 7.2 GET stream buffer 分布
|
||
|
||
```promql
|
||
histogram_quantile(
|
||
0.95,
|
||
sum by (strategy, le) (
|
||
rate(rustfs_io_get_object_stream_buffer_size_bytes_bucket[5m])
|
||
)
|
||
)
|
||
```
|
||
|
||
### 7.3 GET 端到端完成时长
|
||
|
||
```promql
|
||
histogram_quantile(
|
||
0.95,
|
||
sum by (le) (
|
||
rate(rustfs_io_get_object_total_duration_seconds_bucket[5m])
|
||
)
|
||
)
|
||
```
|
||
|
||
## 8. 当前判断建议
|
||
|
||
如果 sequential 在 `1GiB/2GiB`、`c1` 下仍然没有明显优于旧结果,优先检查:
|
||
|
||
1. `large_sequential_readahead` 是否真的命中
|
||
2. buffer size 是否仍停在 `1MiB`
|
||
3. 请求是否实际是 range / encrypted / compressed,从而没走当前优化路径
|
||
|
||
如果 ranged_parallel 明显优于 sequential,再继续补:
|
||
|
||
1. 客户端并行分片数建议
|
||
2. plain 与 encrypted/compressed 的拆分对比
|
||
|
||
## 9. 当前边界
|
||
|
||
这轮实现还没有直接覆盖:
|
||
|
||
1. encrypted `>1GiB GET` 的单独 read-ahead 策略
|
||
2. compressed `>1GiB GET` 的专门 index / range 成本优化
|
||
3. server-side 主动预取缓存
|
||
|
||
因此当前更适合先做:
|
||
|
||
1. plain sequential vs ranged_parallel 基线
|
||
2. 命中策略与吞吐结果收敛
|
||
3. 再决定下一刀是否继续进 encrypted / compressed
|