Skip to content

Add cache benchmarks, stress tests, and fault injection#74

Merged
vansour merged 4 commits intomainfrom
feat/cache-benchmark-stress-faults
Apr 29, 2026
Merged

Add cache benchmarks, stress tests, and fault injection#74
vansour merged 4 commits intomainfrom
feat/cache-benchmark-stress-faults

Conversation

@vansour
Copy link
Copy Markdown
Owner

@vansour vansour commented Apr 29, 2026

Summary

  • add a cache-specific benchmark harness for fill, hit, revalidate, and slice-hit paths
  • add cache stress coverage for large keysets, large cached objects, and reload concurrency
  • add fault-injection regressions for missing cache body files and corrupted shared index metadata
  • update CACHE_ARCHITECTURE_GAPS to mark item 4 as first-pass completed with run commands

Testing

  • cargo test -p rginx-http --lib --locked -- --test-threads=1
  • cargo test -p rginx --test reload --locked -- --test-threads=1
  • ./scripts/run-cache-stress.sh
  • python3 ./scripts/run-cache-benchmark.py --binary ./target/debug/rginx --requests 24 --fill-keys 8 --hit-keys 4 --concurrency 4 --body-bytes 4096 --slice-payload-bytes 16384 --ready-timeout 15
  • ./scripts/run-clippy-gate.sh
  • python3 ./scripts/run-modularization-gate.py

Copilot AI review requested due to automatic review settings April 29, 2026 08:20
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

Warning

Rate limit exceeded

@vansour has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 43 minutes and 43 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 91db0730-d5a7-41ad-9fa7-e940529ddc78

📥 Commits

Reviewing files that changed from the base of the PR and between 0348929 and 6045c8e.

📒 Files selected for processing (1)
  • scripts/run-cache-benchmark.py
📝 Walkthrough

说明

本次变更添加了缓存系统的测试套件、性能基准测试和压力测试工具,以验证缓存在并发流量、配置重加载和故障场景下的稳定性和正确性。

变更内容

群组 / 文件 总结
缓存热性和重加载测试
crates/rginx-app/tests/reload/cache.rs
新增忽略测试,验证并发流量和配置重加载期间缓存条目保持热状态。测试预热缓存后启动4个工作线程发送持续请求,同时迭代改写代理配置、触发信号并验证重加载,最后断言上游请求计数未增加。
缓存恢复和一致性测试
crates/rginx-http/src/cache/tests/lookup/recovery.rs, crates/rginx-http/src/cache/tests/storage_p2.rs
新增异步测试,验证缓存不一致场景的处理:缺失身体文件时将请求视为缓存未命中并清理索引;共享元数据DB损坏时前期同步的条目仍可命中且索引生成号不变。
压力测试套件
crates/rginx-http/src/cache/tests/stress.rs, crates/rginx-http/src/cache/tests/mod.rs
新增压力测试模块和并发负载测试。测试验证大量唯一键并发填充、缓存区条目数量、重复轮次并发查询的HIT一致性;测试单条目大型响应体的重复并发命中且响应体长度精确匹配。
基准测试脚本
scripts/run-cache-benchmark.py
新增Python基准测试工具,启动临时源服务器和rginx实例,支持填充、命中、重验证和分片场景,通过线程池发送并发请求,测量延迟并输出markdown表格统计(吞吐量、平均/p95延迟)。
压力测试运行脚本
scripts/run-cache-stress.sh
新增shell脚本,执行预定义的缓存压力测试矩阵,支持--iterations重复和--release模式,运行cargo test并打印进度。
文档更新
docs/CACHE_ARCHITECTURE_GAPS.md
更新文档记录缓存性能基准测试、负载/压力/持久测试和故障注入回归覆盖的完成进展,列举新增可运行的基准和压力测试入口点。

估计代码审查工作量

🎯 3 (Moderate) | ⏱️ ~25 分钟

可能相关的PR

诗歌

🐰 缓存热性永不冷,并发重载心无忧,
压力测试压压压,基准明确性能优,
恢复一致守稳定,兔子欢呼庆成就!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding cache benchmarks, stress tests, and fault injection capabilities.
Description check ✅ Passed The description clearly relates to the changeset, detailing the addition of cache benchmarks, stress tests, fault-injection coverage, and documentation updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cache-benchmark-stress-faults

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 43 minutes and 43 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@amazon-q-developer amazon-q-developer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR successfully adds a comprehensive cache testing infrastructure including benchmarks, stress tests, and fault injection scenarios. The implementation is well-structured:

Added Components:

  • Cache-specific benchmark harness (run-cache-benchmark.py) for fill, hit, revalidate, and slice-hit paths
  • Stress test suite (run-cache-stress.sh) covering large keysets, large objects, and reload concurrency
  • Fault injection tests for missing cache body files and corrupted shared index metadata
  • Integration test for reload cache preservation under concurrent traffic

Quality Observations:

  • Proper test isolation with ignore attributes and dedicated test runners
  • Comprehensive coverage of cache failure modes
  • Good use of concurrent testing patterns with appropriate synchronization
  • Documentation updated to reflect completion of benchmark/stress testing milestone

The code is ready to merge. All tests are properly marked as ignored and require explicit execution via the provided scripts, preventing CI overhead.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request establishes a robust testing and benchmarking framework for the rginx cache system, including new stress tests for concurrent reloads, large keysets, and large body handling, alongside fault injection scenarios for metadata corruption and missing files. It also introduces a Python-based benchmark script and a Bash-based stress test runner. Feedback identifies a bug in the benchmark script's cache size calculation that causes unintended LRU evictions, suggests enhancing the mock server's HTTP range parsing to support standard prefix/suffix formats, and recommends streaming response bodies in stress tests to mitigate potential memory pressure under high concurrency.

Comment thread scripts/run-cache-benchmark.py Outdated
Comment thread scripts/run-cache-benchmark.py Outdated
Comment thread crates/rginx-http/src/cache/tests/stress.rs Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a cache-focused performance/stress/fault-injection validation layer around the existing rginx HTTP cache, providing repeatable benchmarks plus ignored stress suites that can be driven by scripts.

Changes:

  • Introduces a cache benchmark runner (scripts/run-cache-benchmark.py) that stands up a local origin + real rginx process and measures fill/hit/revalidate/slice-hit paths.
  • Adds a cache stress driver script (scripts/run-cache-stress.sh) to run ignored stress tests across rginx-http (unit-style stress) and rginx reload integration stress.
  • Adds regression tests for cache fault modes (missing body file cleanup; corrupted shared-index SQLite metadata) and documents the new run commands in CACHE_ARCHITECTURE_GAPS.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/run-cache-stress.sh New script to execute the ignored cache stress matrix across crates.
scripts/run-cache-benchmark.py New real-process benchmark harness for cache fill/hit/revalidate/slice-hit scenarios.
docs/CACHE_ARCHITECTURE_GAPS.md Documents the new benchmark/stress/fault-injection “first pass” and how to run it.
crates/rginx-http/src/cache/tests/stress.rs Adds ignored multi-thread stress tests for large keysets and large cached bodies.
crates/rginx-http/src/cache/tests/storage_p2.rs Adds shared-index fault-injection regression for corrupted SQLite metadata.
crates/rginx-http/src/cache/tests/mod.rs Wires in the new stress test module.
crates/rginx-http/src/cache/tests/lookup/recovery.rs Adds missing-body-file fault-injection regression (miss + index/file cleanup).
crates/rginx-app/tests/reload/cache.rs Adds ignored reload+traffic stress test to ensure hot-cache hits survive concurrent reloads.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/run-cache-benchmark.py Outdated
Comment thread scripts/run-cache-benchmark.py
Comment thread scripts/run-cache-benchmark.py Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes Apr 29, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/run-cache-benchmark.py`:
- Around line 86-87: The silent HTTP log override currently defines def
log_message(self, format: str, *args: object) -> None: return which triggers
linter warnings for unused parameters and shadowing the built-in name `format`;
rename the parameters to indicate intentional unused status (e.g., change
`format` to `_format` and `*args` to `*_args` or prefix them with underscores)
or add a brief comment above `log_message` documenting that it's intentionally a
no-op for benchmarks so linters and readers understand the intent; keep the
method body as an empty return to preserve the silent-logging behavior.
- Around line 436-439: The loop that collects results into durations uses
repeated durations.append(future.result()) inside the ThreadPoolExecutor block;
replace that loop by extending durations with a generator expression over
concurrent.futures.as_completed to collect all results at once (e.g.,
durations.extend(f.result() for f in concurrent.futures.as_completed(futures))).
Locate the block that creates futures with executor.submit(run_request, port,
request, timeout) and modify the post-submission collection to use
durations.extend(...) instead of the for future in ...: durations.append(...)
loop to reduce per-item append overhead.
- Line 708: 变量名 "slice" 遮蔽了 Python 内置的 slice 类型;在将 slice_requests(args.requests)
的结果赋值时重命名该变量(例如 requests_slice 或 req_slice),并同步更新后续对该变量的所有引用(大约在后续块引用处,原位于
slice_requests 调用后的 718-728 行);确保函数调用 slice_requests(args.requests)
保持不变,只改变量名以避免命名冲突。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 23477fcb-b1cf-48f4-b618-37d67e3a8362

📥 Commits

Reviewing files that changed from the base of the PR and between 2f4f491 and 0348929.

📒 Files selected for processing (8)
  • crates/rginx-app/tests/reload/cache.rs
  • crates/rginx-http/src/cache/tests/lookup/recovery.rs
  • crates/rginx-http/src/cache/tests/mod.rs
  • crates/rginx-http/src/cache/tests/storage_p2.rs
  • crates/rginx-http/src/cache/tests/stress.rs
  • docs/CACHE_ARCHITECTURE_GAPS.md
  • scripts/run-cache-benchmark.py
  • scripts/run-cache-stress.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test Fast
🧰 Additional context used
🪛 LanguageTool
docs/CACHE_ARCHITECTURE_GAPS.md

[uncategorized] ~65-~65: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:稳定"地"回归
Context: ...盖 - shared index 损坏和文件缺失这类缓存失败模式现在有了稳定的回归入口 ## 长期差距 ### 1. 将缓存写入路径从“全量收集后落盘”升...

(wb4)

🪛 Ruff (0.15.12)
scripts/run-cache-benchmark.py

[error] 86-86: Function argument format is shadowing a Python builtin

(A002)


[warning] 86-86: Unused method argument: format

(ARG002)


[warning] 86-86: Unused method argument: args

(ARG002)


[warning] 150-150: Too many return statements (9 > 6)

(PLR0911)


[warning] 190-190: Boolean-typed positional argument in function definition

(FBT001)


[error] 197-197: Starting a process with a partial executable path

(S607)


[warning] 327-329: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 342-342: Avoid specifying long messages outside the exception class

(TRY003)


[error] 379-379: subprocess call: check for execution of untrusted input

(S603)


[warning] 388-388: Consider moving this statement to an else block

(TRY300)


[warning] 415-418: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 420-423: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 425-428: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 439-439: Use list.extend to create a transformed list

(PERF401)


[warning] 451-451: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


[warning] 573-573: Too many statements (70 > 50)

(PLR0915)


[warning] 598-598: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 680-680: Avoid specifying long messages outside the exception class

(TRY003)


[error] 708-708: Variable slice is shadowing a Python builtin

(A001)


[warning] 729-729: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 745-745: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🔇 Additional comments (9)
crates/rginx-http/src/cache/tests/storage_p2.rs (1)

98-152: LGTM! 共享元数据损坏的故障注入测试覆盖良好。

该测试正确验证了当共享元数据数据库被损坏后,已同步到本地索引的缓存条目仍能正常命中。测试逻辑清晰:先建立共享缓存条目、确认第二个 manager 可以命中、然后注入损坏、最后验证本地命中不受影响。

scripts/run-cache-benchmark.py (1)

740-745: 入口点处理 KeyboardInterrupt 的模式可接受。

当前实现使用退出码 130(SIGINT 标准退出码)是正确的。Linter 建议使用 raise ... from None 来明确表示这是有意的异常转换,但对于 CLI 脚本这种写法是常见且可接受的。

crates/rginx-http/src/cache/tests/mod.rs (1)

21-21: LGTM! 正确添加了 stress 测试模块声明。

docs/CACHE_ARCHITECTURE_GAPS.md (1)

49-66: LGTM! 文档清晰地记录了新增的缓存测试体系。

新增内容准确描述了本 PR 添加的 benchmark、stress 测试和故障注入回归覆盖,并提供了可执行的运行命令。这对后续维护和使用都很有帮助。

注:LanguageTool 关于"稳定的回归入口"的语法建议是误报,当前用法作为定语修饰"回归入口"是正确的。

crates/rginx-http/src/cache/tests/lookup/recovery.rs (1)

199-250: LGTM! 缓存 body 文件缺失的故障注入测试覆盖完善。

测试正确验证了当缓存 body 文件缺失时:

  1. 请求被视为 MISS 而非 HIT
  2. 不会触发后台更新
  3. 索引条目被正确清理
  4. 大小计数归零
  5. 残留的元数据文件也被清理

Line 247 的 drop(index) 确保在检查文件存在性之前释放索引锁,这是正确的做法。

scripts/run-cache-stress.sh (1)

1-80: LGTM! Stress 测试运行脚本结构清晰。

脚本提供了良好的 CLI 接口,支持 --iterations--release 选项,参数验证完整。使用矩阵驱动方式组织测试用例,便于扩展和维护。

crates/rginx-app/tests/reload/cache.rs (1)

52-139: LGTM! Reload 并发热点缓存测试覆盖了关键场景。

测试通过并行流量 + 重复 SIGHUP 重载来验证缓存条目在配置重载期间保持可用。关键验证点:

  1. 预热后的缓存条目始终返回 HIT
  2. 重载期间没有额外的 upstream 请求
  3. 没有请求失败或返回非预期状态

这对确保生产环境下配置重载不影响缓存命中率很有价值。

crates/rginx-http/src/cache/tests/stress.rs (2)

40-114: LGTM! 大 key 数并行填充与命中的 stress 测试设计合理。

测试正确验证了:

  1. 256 个唯一 key 的并行填充全部返回 MISS
  2. 填充后索引条目数量正确
  3. 多轮并行命中全部返回 HIT 且 body 内容一致

使用 JoinSet 管理并发任务是惯用做法,Bytes::clone() 是 O(1) 操作,不会造成性能问题。


116-167: LGTM! 大对象持续并行命中的 stress 测试覆盖充分。

测试使用 256KB body、48 并发、6 轮的配置验证了大响应体在高并发读取下的稳定性。response_body_len 辅助函数使用流式读取方式计算 body 长度,避免一次性加载到内存,这是正确的做法。

Comment thread scripts/run-cache-benchmark.py Outdated
Comment thread scripts/run-cache-benchmark.py Outdated
Comment thread scripts/run-cache-benchmark.py Outdated
@vansour vansour enabled auto-merge April 29, 2026 08:48
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab098070c3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/run-cache-benchmark.py
@vansour vansour dismissed coderabbitai[bot]’s stale review April 29, 2026 08:57

Addressed in commit 6045c8e; dismissing stale bot change request so the PR can merge.

@vansour vansour merged commit 4e817fc into main Apr 29, 2026
7 checks passed
@vansour vansour deleted the feat/cache-benchmark-stress-faults branch April 29, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants