Skip to content

Optimize the parallelizing the output of the transaction execution - #4829

Open
jackzhhuang wants to merge 3 commits into
dual-verse-dagfrom
parallize-vm-execute-if-needed
Open

Optimize the parallelizing the output of the transaction execution#4829
jackzhhuang wants to merge 3 commits into
dual-verse-dagfrom
parallize-vm-execute-if-needed

Conversation

@jackzhhuang

@jackzhhuang jackzhhuang commented Mar 9, 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

  • Refactor

    • Optimized transaction materialization to mix parallel and sequential execution when needed, improving throughput for complex write patterns and group conflicts while preserving public behavior.
  • Bug Fixes

    • Added invariant checks to detect and report unconsumed outputs after mixed materialization, improving correctness and error reporting.
  • Tests

    • Added tests and an ignored benchmark for sparse conflict scenarios and parity with the legacy sequential path; updated a merge-block test to validate the correct selected parent before applying a merge.
  • Chores / CI

    • Bumped a few dev/workspace dependency versions and added Dependabot labeling; added a workflow to auto-enable Dependabot auto-merge when criteria are met.

@jackzhhuang jackzhhuang self-assigned this Mar 9, 2026
@coderabbitai

coderabbitai Bot commented Mar 9, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors parallel materialization to support mixed-mode execution: classifies transactions into parallel-safe and sequential sets, runs safe candidates in parallel with per-candidate group caches, then materializes sequential ones in original order while preserving shared state and validating invariants; also updates a chain test and CI/dependency files.

Changes

Cohort / File(s) Summary
Parallel materialization logic
vm2/vm-runtime/src/parallel_executor/mod.rs
Refactors materialize_parallel_outputs into helpers (is_group_write_op, materialize_parallel_candidate), replaces group-dup tracking with group_touch_counts, implements mixed-mode execution (partition into parallel_candidates and sequential_outputs), executes parallel candidates via Rayon with per-candidate group caches, then applies sequential materialization in original txn order; adds invariant check for unconsumed outputs and tightens the fast no-groups shortcut.
Tests & benchmarks for materialization
vm2/vm-runtime/src/.../tests
Adds build_sparse_conflict_case, legacy all-seq baseline materialize_parallel_outputs_legacy_all_seq, comparator mixed_materialization_matches_legacy_all_seq_outputs, and an ignored benchmark bench_mixed_materialization_sparse_conflicts validating equality and measuring timings.
Chain service test
chain/service/src/chain_service.rs
Updates test_get_current_block_color_merge_blue to compute the merge block's selected parent and apply the merge block to whichever chain (main or fork) matches that parent; fails if neither matches.
CI / Dependabot workflows
.github/dependabot.yml, .github/workflows/dependabot_auto_merge.yml
Adds Dependabot labels and a new auto-merge workflow that enables squash auto-merge for Dependabot PRs targeting dual-verse-dag when the Build-and-Test run succeeds.
Dependency bumps
Cargo.toml, simnet/Cargo.toml
Bumps rustc-hash 2.1.1→2.1.2 and proptest 1.10→1.11 (workspace and simnet dev-dep).

Sequence Diagram(s)

sequenceDiagram
    participant Driver as Executor (materialize_parallel_outputs)
    participant Parallel as Parallel Worker (Rayon)
    participant Seq as Sequential Materializer
    participant SVC as StateViewCache
    participant GC as GroupCache

    rect rgba(200,220,255,0.5)
    Driver->>Driver: classify txns -> parallel_candidates + sequential_outputs
    end

    rect rgba(200,255,200,0.5)
    Driver->>Parallel: spawn materialize_parallel_candidate per candidate
    Parallel->>GC: use per-candidate group cache
    Parallel->>SVC: read-state via shared StateViewCache (read-only)
    Parallel-->>Driver: return (txn_idx, TransactionOutput)
    end

    rect rgba(255,230,200,0.5)
    Driver->>Seq: iterate ordered txns, apply sequential materialization for sequential_outputs
    Seq->>GC: update shared group_cache (patches)
    Seq->>SVC: update/read shared StateViewCache as needed
    Seq-->>Driver: write final outputs in order
    end

    Driver->>Driver: invariant check -> error if unconsumed outputs remain
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • sanlee42
  • simonjiao
  • nkysg

Poem

I hopped through bytes and tangled threads,
Split safe hops from knotted beds,
Parallel carrots, sequential greens,
I stitched outputs back in ordered scenes,
Thump-thump — a rabbit patching dreams 🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title mentions 'parallelizing' but contains a grammatical error ('Optimize the parallelizing') and is somewhat vague. While it references a real part of the changeset (parallel execution optimization), it does not clearly convey the main technical change (mixed-mode parallel/sequential materialization with transaction partitioning).

✏️ 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 parallize-vm-execute-if-needed

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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 887e65a9c7

ℹ️ 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 vm2/vm-runtime/src/parallel_executor/mod.rs

@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

🧹 Nitpick comments (1)
vm2/vm-runtime/src/parallel_executor/mod.rs (1)

1221-1250: The new tests still miss the group_dup and delayed-field branches.

build_sparse_conflict_case() always creates a fresh group_key on Line 1221, and the test/bench calls here keep using VersionedDelayedFields::empty() (for example Line 1372 and Line 1462). So the new mixed path is only validated through the agg_v1 split, while the duplicated-group and delayed-field materialization paths can regress unnoticed.

Also applies to: 1363-1479

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

In `@vm2/vm-runtime/src/parallel_executor/mod.rs` around lines 1221 - 1250,
build_sparse_conflict_case currently always generates a fresh group_key and uses
VersionedDelayedFields::empty(), so tests never exercise the group_dup and
delayed-field materialization branches; modify build_sparse_conflict_case to (1)
insert at least one duplicate group_key for a different txn index to trigger the
group_dup logic (reuse the existing StateKey::raw("group-{...}") creation but
intentionally reuse the same key for a second transaction) and (2) construct and
attach non-empty VersionedDelayedFields for one or more transactions (instead of
VersionedDelayedFields::empty()) so the delayed-field materialization path runs;
update any test callers that rely on this helper so they validate the dup-group
and delayed-field behavior as well.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@vm2/vm-runtime/src/parallel_executor/mod.rs`:
- Around line 1221-1250: build_sparse_conflict_case currently always generates a
fresh group_key and uses VersionedDelayedFields::empty(), so tests never
exercise the group_dup and delayed-field materialization branches; modify
build_sparse_conflict_case to (1) insert at least one duplicate group_key for a
different txn index to trigger the group_dup logic (reuse the existing
StateKey::raw("group-{...}") creation but intentionally reuse the same key for a
second transaction) and (2) construct and attach non-empty
VersionedDelayedFields for one or more transactions (instead of
VersionedDelayedFields::empty()) so the delayed-field materialization path runs;
update any test callers that rely on this helper so they validate the dup-group
and delayed-field behavior as well.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a20e19d-2889-4d9e-86d4-439d1b1e672a

📥 Commits

Reviewing files that changed from the base of the PR and between c0188db and 887e65a.

📒 Files selected for processing (1)
  • vm2/vm-runtime/src/parallel_executor/mod.rs

Comment thread vm2/vm-runtime/src/parallel_executor/mod.rs
@jackzhhuang
jackzhhuang requested a review from sanlee42 March 9, 2026 09:08

@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.

🧹 Nitpick comments (2)
vm2/vm-runtime/src/parallel_executor/mod.rs (2)

530-541: Minor: simplify redundant condition.

Line 530 already computes has_agg_v1, but line 535 re-checks vm_output.aggregator_v1_delta_set().is_empty(). Consider using the existing variable for consistency.

🔧 Suggested simplification
             if !has_delayed && vm_output.aggregator_v1_delta_set().is_empty() && !has_group_ops {
+            if !has_delayed && !has_agg_v1 && !has_group_ops {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vm2/vm-runtime/src/parallel_executor/mod.rs` around lines 530 - 541, The
condition redundantly recomputes vm_output.aggregator_v1_delta_set().is_empty()
instead of using the already-computed has_agg_v1; update the if-condition to use
has_agg_v1 (i.e., check !has_delayed && !has_agg_v1 && !has_group_ops) so the
logic is consistent and avoid re-accessing vm_output, keeping the subsequent
call to vm_output.into_transaction_output() and the
VMStatus::error(StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, ...)
handling unchanged.

1366-1388: Good comparison test; consider adding a no-conflict case.

This test validates the mixed path against the legacy sequential path for the conflict scenario. Consider adding a complementary test where conflict_a and conflict_b don't trigger needs_sequential (e.g., no agg_v1 deltas) to exercise the pure parallel path at lines 464–480.

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

In `@vm2/vm-runtime/src/parallel_executor/mod.rs` around lines 1366 - 1388, Add a
complementary test that exercises the pure-parallel path (no sequential
fallback) by creating inputs where conflict_a and conflict_b do not trigger
needs_sequential (no agg_v1 deltas) and asserting materialize_parallel_outputs
equals materialize_parallel_outputs_legacy_all_seq; implement a new test
function (e.g., mixed_materialization_matches_legacy_no_conflict_outputs) that
uses a builder producing a no-conflict scenario (either add a
build_no_conflict_case helper or call build_sparse_conflict_case with parameters
that produce no agg_v1 deltas), call materialize_parallel_outputs and
materialize_parallel_outputs_legacy_all_seq with VersionedDelayedFields::empty()
and Arc::new(DelayedFieldCache::default()) and the returned state_views, unwrap
the results, and assert_eq!(mixed, legacy).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@vm2/vm-runtime/src/parallel_executor/mod.rs`:
- Around line 530-541: The condition redundantly recomputes
vm_output.aggregator_v1_delta_set().is_empty() instead of using the
already-computed has_agg_v1; update the if-condition to use has_agg_v1 (i.e.,
check !has_delayed && !has_agg_v1 && !has_group_ops) so the logic is consistent
and avoid re-accessing vm_output, keeping the subsequent call to
vm_output.into_transaction_output() and the
VMStatus::error(StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, ...)
handling unchanged.
- Around line 1366-1388: Add a complementary test that exercises the
pure-parallel path (no sequential fallback) by creating inputs where conflict_a
and conflict_b do not trigger needs_sequential (no agg_v1 deltas) and asserting
materialize_parallel_outputs equals materialize_parallel_outputs_legacy_all_seq;
implement a new test function (e.g.,
mixed_materialization_matches_legacy_no_conflict_outputs) that uses a builder
producing a no-conflict scenario (either add a build_no_conflict_case helper or
call build_sparse_conflict_case with parameters that produce no agg_v1 deltas),
call materialize_parallel_outputs and
materialize_parallel_outputs_legacy_all_seq with VersionedDelayedFields::empty()
and Arc::new(DelayedFieldCache::default()) and the returned state_views, unwrap
the results, and assert_eq!(mixed, legacy).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e93f98f-39c2-471a-ad06-02ff27c73dcf

📥 Commits

Reviewing files that changed from the base of the PR and between 887e65a and 43da76b.

📒 Files selected for processing (1)
  • vm2/vm-runtime/src/parallel_executor/mod.rs

@jackzhhuang
jackzhhuang force-pushed the parallize-vm-execute-if-needed branch from 43da76b to cf3eac7 Compare March 25, 2026 04:06

@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.

🧹 Nitpick comments (1)
vm2/vm-runtime/src/parallel_executor/mod.rs (1)

1458-1554: Consider additional edge case coverage.

The benchmark test provides good validation with sparse conflicts. Consider adding unit tests for edge cases:

  • All transactions require sequential processing (conflicts at indices 0 and 1)
  • No transactions require sequential processing (no conflicts)
  • Single transaction requiring sequential (only one conflict index)

This would increase confidence in boundary conditions.

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

In `@vm2/vm-runtime/src/parallel_executor/mod.rs` around lines 1458 - 1554, The
benchmark covers a sparse-conflict scenario but lacks boundary tests; add small
unit tests calling build_sparse_conflict_case and comparing
materialize_parallel_outputs_legacy_all_seq and materialize_parallel_outputs
outputs for three edge cases: (1) all transactions sequential (use conflict
indices like 0 and 1 so every txn conflicts), (2) no sequential conflicts (empty
or distinct non-conflicting indices), and (3) single-transaction sequential case
(only one conflict index). Create three new #[test] functions (non-ignored) that
construct inputs via build_sparse_conflict_case with tiny TXN_COUNT, invoke both
materialize_parallel_outputs_legacy_all_seq and materialize_parallel_outputs
with the same VersionedDelayedFields::empty() and DelayedFieldCache, unwrap the
results and assert_eq! on outputs to validate behavioral parity for edge
boundaries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@vm2/vm-runtime/src/parallel_executor/mod.rs`:
- Around line 1458-1554: The benchmark covers a sparse-conflict scenario but
lacks boundary tests; add small unit tests calling build_sparse_conflict_case
and comparing materialize_parallel_outputs_legacy_all_seq and
materialize_parallel_outputs outputs for three edge cases: (1) all transactions
sequential (use conflict indices like 0 and 1 so every txn conflicts), (2) no
sequential conflicts (empty or distinct non-conflicting indices), and (3)
single-transaction sequential case (only one conflict index). Create three new
#[test] functions (non-ignored) that construct inputs via
build_sparse_conflict_case with tiny TXN_COUNT, invoke both
materialize_parallel_outputs_legacy_all_seq and materialize_parallel_outputs
with the same VersionedDelayedFields::empty() and DelayedFieldCache, unwrap the
results and assert_eq! on outputs to validate behavioral parity for edge
boundaries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee61d76a-0940-40c1-9354-2f528c21f58f

📥 Commits

Reviewing files that changed from the base of the PR and between 43da76b and cf3eac7.

📒 Files selected for processing (1)
  • vm2/vm-runtime/src/parallel_executor/mod.rs

@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

🤖 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/dependabot_auto_merge.yml:
- Line 18: Replace the mutable GitHub Action reference
"actions/github-script@v7" with an immutable pinned commit SHA: find the step
that uses actions/github-script (the line containing uses:
actions/github-script@v7), look up the repository's commit SHA for the desired
v7 release tag (via the actions/github-script repo on GitHub) and update the
uses value to uses: actions/github-script@<full-commit-sha>; ensure you use the
full 40-character commit SHA so the workflow is pinned to an immutable revision.
🪄 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: 379d51ef-5bb3-48dc-8f31-06a6a2696b03

📥 Commits

Reviewing files that changed from the base of the PR and between 786d717 and cc3a814.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • .github/dependabot.yml
  • .github/workflows/dependabot_auto_merge.yml
  • Cargo.toml
  • simnet/Cargo.toml
✅ Files skipped from review due to trivial changes (3)
  • simnet/Cargo.toml
  • .github/dependabot.yml
  • Cargo.toml

runs-on: ubuntu-latest
steps:
- name: Enable auto-merge for Dependabot PRs
uses: actions/github-script@v7

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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find workflow action refs that are not pinned to a full 40-char SHA.
fd -HI -e yml -e yaml '' .github/workflows \
  -x rg -nP '^\s*uses:\s*[^@\s]+@(?!(?:[0-9a-fA-F]{40})\b)[^ \t#]+' {}

# Optional: list github-script tags and backing SHAs to choose a pin.
gh api repos/actions/github-script/tags --jq '.[0:20][] | "\(.name)\t\(.commit.sha)"'

Repository: starcoinorg/starcoin

Length of output: 2345


🏁 Script executed:

cat -n .github/workflows/dependabot_auto_merge.yml

Repository: starcoinorg/starcoin

Length of output: 3280


Pin actions/github-script to an immutable commit SHA.

Line 18 uses a mutable tag (@v7). Since this workflow has write permissions, an unpinned action tag presents a supply-chain risk if the tag is reassigned.

Suggested change
      - name: Enable auto-merge for Dependabot PRs
-       uses: actions/github-script@v7
+       uses: actions/github-script@<40-char-commit-sha>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/dependabot_auto_merge.yml at line 18, Replace the mutable
GitHub Action reference "actions/github-script@v7" with an immutable pinned
commit SHA: find the step that uses actions/github-script (the line containing
uses: actions/github-script@v7), look up the repository's commit SHA for the
desired v7 release tag (via the actions/github-script repo on GitHub) and update
the uses value to uses: actions/github-script@<full-commit-sha>; ensure you use
the full 40-character commit SHA so the workflow is pinned to an immutable
revision.

@jackzhhuang
jackzhhuang force-pushed the parallize-vm-execute-if-needed branch from cc3a814 to 786d717 Compare March 31, 2026 09:26
@jackzhhuang
jackzhhuang force-pushed the parallize-vm-execute-if-needed branch from 786d717 to c07d62a Compare April 8, 2026 02:22
@simonjiao

Copy link
Copy Markdown
Contributor

@jackhuang run ci with k8s tag

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.

3 participants