Skip to content

Dio/tps optimization agent loop - #4849

Open
lushengguo wants to merge 27 commits into
dual-verse-dagfrom
dio/tps_optimization_agent_loop
Open

Dio/tps optimization agent loop#4849
lushengguo wants to merge 27 commits into
dual-verse-dagfrom
dio/tps_optimization_agent_loop

Conversation

@lushengguo

@lushengguo lushengguo commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Other information

Summary by CodeRabbit

  • Chores
    • Increased benchmark job timeout from 30 to 60 minutes.
    • Improved benchmark pipeline with conditional base branch comparison and individual step timeouts.
    • Enhanced benchmark result handling and comparison logic.

…JSON output

- Port starcoin-execute-bench from align-interface-for-value-serde branch
- Add pipeline.rs module for 4-stage timing (TxPool Verify, Block Build, VM Execute, State Commit)
- Add JSON export for AI agent loop consumption (benchmark_results.json)
- Add StageTiming struct with min/max/avg/median/p95/p99/throughput metrics
- Add set_max_per_sender method to TxPoolConfig
- Update workspace Cargo.toml to include new crate

The framework now supports:
- Full-chain benchmark with real node
- Transaction latency tracking (Added -> Executed)
- Block-level TPS statistics
- SVG visualization with plotters
- JSON output for automated analysis
Add a global timing collector to measure pipeline stage durations:
- TxPool Verify: transaction signature validation
- Block Build: DAG block packaging
- VM Execute: transaction execution
- State Commit: state persistence

Integrate timing instrumentation into:
- txpool/pool_client.rs: TxPool Verify timing
- miner/block_builder_service.rs: Block Build timing
- chain/chain.rs: VM Execute and State Commit timing
- test-helper: expose timing data after node stop
Add --agent-mode to starcoin-execute-bench with:
- BottleneckAnalyzer: identify pipeline bottlenecks by time percentage
- OptimizationSuggester: generate actionable optimization suggestions
- HistoryStore: track benchmark history for trend analysis
- RegressionDetector: detect performance regressions vs baseline
- AgentLoop: orchestrate analysis and generate structured output

Output includes:
- Pipeline stage timing breakdown
- Bottleneck severity classification
- Prioritized optimization suggestions
- Regression alerts with severity levels
- Action items for AI agents

Usage: cargo run -p starcoin-execute-bench -- --agent-mode
Add advanced optimization loop components:
- KnowledgeBase: record optimization history and learn patterns
- StrategyTracker: manage optimization attempt lifecycle
- ConfigTuner: auto-tune configuration parameters with rollback
- ExperimentFramework: A/B testing with statistical significance
- IterationController: orchestrate full optimization loop

This enables automated optimization cycles:
Analyze → Select Strategy → Apply → Verify → Commit/Rollback → Learn

Note: Knowledge persistence is designed to be complemented by
AI-written documentation in docs/ for team sharing.
Add team-shared optimization documentation:
- docs/OPTIMIZATION_KNOWLEDGE.md: learned strategies and patterns
- docs/BENCHMARK_HISTORY.md: historical benchmark results
- docs/LESSONS_LEARNED.md: successes, failures, and insights
- docs/adr/: Architecture Decision Records for major changes

Add .github/copilot-instructions.md to guide AI agents:
- Read optimization docs before suggesting changes
- Update docs after successful optimizations
- Create ADRs for architectural decisions

This enables knowledge sharing across team members and AI agents
through version-controlled documentation.
- Remove unused modules (iteration, config_tuner, experiment, strategy, pipeline)
- Remove AI optimization docs (will be regenerated as needed)
- Add benchmark README with usage instructions
- Add #[allow(dead_code)] for future-use methods
- Remove iterate/target-tps CLI options (not needed for CI)
- Fix unused import warnings
- Remove CLI parameters: --history-dir, --knowledge-dir, --tags, --agent-output
- Delete modules: history.rs, knowledge.rs, regression.rs, suggester.rs
- Simplify agent_loop.rs to pure stateless analysis
- Benchmark now outputs analysis directly without persisting data
- Add block_count to BenchmarkStats for sample size tracking
- Increase default account-count from 20 to 8000 for better sampling
- Display sample quality indicator (GOOD/ACCEPTABLE/LOW)
- Highlight Median TPS as CI recommended metric (more stable)
- Show clear CI-recommended vs raw metrics in output
…lock_count

- 8000 accounts caused funding timeout (only 360/8000 funded in 180s)
- Add #[serde(default)] to block_count for backward compatibility
- 4000 accounts provides good balance of stability and speed
Stable TPS calculation:
1. Exclude first and last blocks (edge effects)
2. Use trimmed mean (remove top/bottom 10% outliers)
3. Only use middle blocks for calculation

New fields in BenchmarkStats:
- stable_tps: the CI recommended metric
- middle_block_count: number of blocks used for stable calculation

Expected stability improvement: ±50% -> ±10%
- Add --rounds CLI parameter (default: 3) to repeat benchmark transactions
- More rounds = more blocks = better statistical significance
- Auto-calculate txpool size based on rounds
- Each round reuses same accounts with incrementing sequence numbers
…ntervals

When STARCOIN_FIXED_BLOCK_TIME is set, DummyConsensus uses fixed sleep time
equal to difficulty (block_time_target) instead of random range.
This reduces TPS measurement variance in benchmarks.
Adds a convenient CLI option to enable fixed block time intervals.
Equivalent to setting STARCOIN_FIXED_BLOCK_TIME env var.
Root cause of TPS variance identified and fixed:

PROBLEM:
- TPS calculation used event processing time (exec_ts) as transaction execution time
- But exec_ts is recorded when NewHeadBlock event is processed, not when txns execute
- Event processing includes try_submit_next_batch() which is slow
- This causes event queue delays, making exec_ts unreliable

SOLUTION:
- New calculate_tps_from_block_timestamps() method
- Uses block header timestamps (set when block is created by miner)
- TPS = total_txns / (last_block_ts - first_block_ts)
- Not affected by event queue delays

REMAINING VARIANCE (~25% CV):
- Real execution time variance due to system load, GC, I/O
- This is actual performance variance, not measurement error
- For CI: recommend running 3-5 times and taking median
…istence

- Add --prepare-bench mode: funds accounts, signs transactions, saves
  chain data + signed txns to disk for reuse across benchmark runs
- Add --load-bench mode: loads pre-signed txns, copies chain data to
  temp dir, starts node, imports txns to txpool, runs benchmark
- Fix expire_time: use now_secs()+40000 instead of +1 year to stay
  within on-chain transaction_timeout (86400s) upper bound check
- Change --rounds default from 3 to 10, --settle-delay-ms from 10000 to 3000
- Add build_node_config() with disable_seed=true for isolated benchmarks
- Add start_node_and_wait() with sync state polling
- Add GenerateBlockEvent broadcast after direct txpool import
- Remove debug try_read() method from TxPoolService Inner
- Remove stale commented-out inner_status code
- Fix clippy::unwrap_or_default: use or_default() instead of or_insert_with(Vec::new) in pipeline-timing
- Fix clippy::collapsible_if: merge nested if conditions in results.rs
- Fix clippy::useless_conversion: remove redundant .try_into() on TokenCode in main.rs
- Fix trailing whitespace in chain.rs, pool_client.rs
- Add CI benchmark workflow (tps_benchmark.yml) and comparison script (bench_compare.py)
- Add pipeline stage-level regression detection with per-stage thresholds
# Conflicts:
#	Cargo.lock
#	sync/starcoin-execute-bench/Cargo.toml
#	sync/starcoin-execute-bench/src/main.rs
#	sync/starcoin-execute-bench/src/results.rs
The test passed observed_tps=50.0 but the theoretical max TPS from the
slowest stage (Block Build avg_ms=50.0) is only 1000/50=20.0. Since
theoretical_max < observed, improvement_potential_pct was 0.0, failing
the assertion. Changed observed_tps to 15.0 to match realistic data.
- Fix typo 'Stat)less' -> 'Stateless' in agent_loop.rs doc comment
- Add 'text' language tag to fenced code block in README.md (MD040)
- Remove trailing '--' from git checkout commands in CI workflow
  (was incorrectly used as path separator instead of ref checkout)
- Detect supported flags via --help instead of hardcoding
- Handle missing benchmark_results.json from older bench binary
- Guard PR comment step with has_report output flag
- Guard compare step against missing bench_current.json
@lushengguo
lushengguo requested a review from sanlee42 as a code owner April 16, 2026 11:23
@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Modified the TPS benchmark GitHub Actions workflow to increase job timeout from 30 to 60 minutes. Restructured the pipeline to save the current-branch benchmark binary, conditionally checkout and benchmark the base branch (dual-verse-dag), then compare results. Added per-step timeouts and conditional execution based on base branch availability.

Changes

Cohort / File(s) Summary
Benchmark Workflow Configuration
.github/workflows/tps_benchmark.yml
Increased job-level timeout (30→60 min) and restructured pipeline: saves current-branch benchmark binary, adds conditional base-branch checkout/build with 10-min step timeouts, sets Rust env vars, and conditionally runs comparison with base results. Control flow now depends on base branch availability via prepare_base.outputs.has_base.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • sanlee42
  • welbon
  • jackzhhuang

Poem

🐰 Hop hop, the benchmarks now run faster,
With branch-switching grace, avoiding disaster!
Current and base in a synchronized dance,
Timeouts doubled—no more failed spans! ⚡
Results compared, the truth shall appear clear. 🎯

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Dio/tps optimization agent loop' is vague and uses non-descriptive terms that do not clearly convey the main change, which is a significant refactor of the benchmark workflow pipeline with conditional base branch runs and improved timing controls. Replace with a more descriptive title that reflects the primary workflow change, such as 'Refactor TPS benchmark workflow with conditional base branch runs and improved timeouts' or similar that clarifies the actual changeset.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 dio/tps_optimization_agent_loop

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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/workflows/tps_benchmark.yml (2)

124-161: ⚠️ Potential issue | 🟠 Major

Optional base benchmark can hard-fail the whole job.

This step is treated as optional (has_base gating), but set -euo pipefail plus the benchmark pipeline means any non-zero base run aborts the job before current-run/report generation.

Proposed fix
-          set -euo pipefail
+          set -uo pipefail
@@
-          STARCOIN_FIXED_BLOCK_TIME=1 ./target/release/starcoin-execute-bench \
-            $BASE_ARGS \
-            2>&1 | tail -20
+          if ! STARCOIN_FIXED_BLOCK_TIME=1 ./target/release/starcoin-execute-bench \
+            $BASE_ARGS \
+            2>&1 | tail -20; then
+            echo "⚠️  Base benchmark command failed — skipping base comparison."
+          fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/tps_benchmark.yml around lines 124 - 161, The base
benchmark run (STARCOIN_FIXED_BLOCK_TIME=1
./target/release/starcoin-execute-bench ...) can exit non-zero and, because of
set -euo pipefail, will abort the whole job; change the step so the base bench
is executed without causing the script to exit on failure (for example run the
command in a way that its non-zero exit is tolerated and capture its exit code
into a variable), still capture its stdout/stderr (tail -20 or log file) and
then check for the existence of benchmark_results.json to set has_base and copy
to bench_base.json; update references to HELP_TEXT and BASE_ARGS handling remain
unchanged.

103-105: ⚠️ Potential issue | 🟠 Major

Workflow never switches back to PR/current checkout after running base branch.

After Line 104 (git checkout "$BASE_BRANCH"), subsequent steps (including scripts/bench_compare.py) execute from base-branch files, not the PR’s files. That can silently compare with the wrong script version.

Proposed fix
+      - name: Switch back to PR/current commit
+        run: |
+          set -euo pipefail
+          git checkout --force "${GITHUB_SHA}"
+          git submodule update --init --recursive || true

Also applies to: 166-212

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/tps_benchmark.yml around lines 103 - 105, The workflow
checks out the base branch with the command git checkout "$BASE_BRANCH" (and
updates submodules) but never restores the PR/current checkout, so later steps
(e.g., scripts/bench_compare.py) run against base-branch files; after the
base-branch work completes, add a step to restore the original PR commit by
checking out the pull-request commit (use git checkout "$GITHUB_SHA" or capture
the original HEAD before switching and run git checkout "$ORIGINAL_HEAD"), then
update submodules for the PR if needed; apply the same restore change to the
other block referenced (lines 166-212) so all comparisons run from the PR's
files.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/tps_benchmark.yml:
- Around line 95-101: The script copies ./target/release/starcoin-execute-bench
to ./bench_current_bin before running git stash --include-untracked, which
causes bench_current_bin to be removed and later steps to fail; move the cp
./target/release/starcoin-execute-bench ./bench_current_bin line to after the
git stash --include-untracked call (and apply the same reordering to the second
occurrence around lines 171-172) so bench_current_bin is created after stashing
and remains available for later use.

---

Outside diff comments:
In @.github/workflows/tps_benchmark.yml:
- Around line 124-161: The base benchmark run (STARCOIN_FIXED_BLOCK_TIME=1
./target/release/starcoin-execute-bench ...) can exit non-zero and, because of
set -euo pipefail, will abort the whole job; change the step so the base bench
is executed without causing the script to exit on failure (for example run the
command in a way that its non-zero exit is tolerated and capture its exit code
into a variable), still capture its stdout/stderr (tail -20 or log file) and
then check for the existence of benchmark_results.json to set has_base and copy
to bench_base.json; update references to HELP_TEXT and BASE_ARGS handling remain
unchanged.
- Around line 103-105: The workflow checks out the base branch with the command
git checkout "$BASE_BRANCH" (and updates submodules) but never restores the
PR/current checkout, so later steps (e.g., scripts/bench_compare.py) run against
base-branch files; after the base-branch work completes, add a step to restore
the original PR commit by checking out the pull-request commit (use git checkout
"$GITHUB_SHA" or capture the original HEAD before switching and run git checkout
"$ORIGINAL_HEAD"), then update submodules for the PR if needed; apply the same
restore change to the other block referenced (lines 166-212) so all comparisons
run from the PR's files.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b115bbf-224c-414f-af46-2a5476649e4a

📥 Commits

Reviewing files that changed from the base of the PR and between 919cd3a and d9d1eaa.

📒 Files selected for processing (1)
  • .github/workflows/tps_benchmark.yml

Comment on lines +95 to 101
# Preserve the current-branch binary so the base build can overwrite target/
cp ./target/release/starcoin-execute-bench ./bench_current_bin

BASE_BRANCH="dual-verse-dag"
CURRENT_SHA=$(git rev-parse HEAD)

# Stash any untracked files from the current-branch run
# Stash any untracked files from the current-branch build
git stash --include-untracked || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

bench_current_bin is stashed away before it is used.

At Line 96 you save ./bench_current_bin, then at Line 101 git stash --include-untracked removes it from the working tree. The later run at Line 171 can fail with “No such file or directory”.

Proposed fix
-          cp ./target/release/starcoin-execute-bench ./bench_current_bin
+          cp ./target/release/starcoin-execute-bench "${RUNNER_TEMP}/bench_current_bin"
@@
-          STARCOIN_FIXED_BLOCK_TIME=1 ./bench_current_bin \
+          STARCOIN_FIXED_BLOCK_TIME=1 "${RUNNER_TEMP}/bench_current_bin" \

Also applies to: 171-172

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/tps_benchmark.yml around lines 95 - 101, The script copies
./target/release/starcoin-execute-bench to ./bench_current_bin before running
git stash --include-untracked, which causes bench_current_bin to be removed and
later steps to fail; move the cp ./target/release/starcoin-execute-bench
./bench_current_bin line to after the git stash --include-untracked call (and
apply the same reordering to the second occurrence around lines 171-172) so
bench_current_bin is created after stashing and remains available for later use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant