Files
rustfs/docs/operations/issue-713-gt1g-get-ops-guide-zh.md
T
houseme 96b1f5c373 feat(storage): optimize gt1g get read path (#3860)
* 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
2026-06-25 20:12:08 +08:00

5.9 KiB
Raw Blame History

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 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. curlsize_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 baselinesequential + ranged_parallel

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 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 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. 输出目录

默认输出:

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 是否命中大对象策略

查询:

sum by (strategy) (
  increase(rustfs_io_get_object_stream_strategy_total[5m])
)

预期:

  1. >1GiB 顺序 GET 应出现 large_sequential_readahead

7.2 GET stream buffer 分布

histogram_quantile(
  0.95,
  sum by (strategy, le) (
    rate(rustfs_io_get_object_stream_buffer_size_bytes_bucket[5m])
  )
)

7.3 GET 端到端完成时长

histogram_quantile(
  0.95,
  sum by (le) (
    rate(rustfs_io_get_object_total_duration_seconds_bucket[5m])
  )
)

8. 当前判断建议

如果 sequential 在 1GiB/2GiBc1 下仍然没有明显优于旧结果,优先检查:

  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