Skip to content

perf: rust backed PTC sampling#9263

Open
guha-rahul wants to merge 5 commits intoChainSafe:unstablefrom
guha-rahul:compute_rust_ptc
Open

perf: rust backed PTC sampling#9263
guha-rahul wants to merge 5 commits intoChainSafe:unstablefrom
guha-rahul:compute_rust_ptc

Conversation

@guha-rahul
Copy link
Copy Markdown
Contributor

@guha-rahul guha-rahul commented Apr 23, 2026

Motivation

#9013 and https://github.com/ChainSafe/lodestar/pull/9211/changes/BASE..27a20754340c6fe83a3822f3ba219ac39c3c1efa#r3074070771 highlight that computing ptc sampling is costly. T he sanity tests needed a 30s → 60s timeout bump. This PR moves the resource intensive into Rust

Description

Performance

 computePayloadTimelinessCommitteeForSlot - pure TS vs Rust magic (250k-1M validators)
    ✔ naive TS - naiveComputePayloadTimelinessCommitteeForSlot - 25000    745.4242 ops/s    1.341518 ms/op   x0.963        469 runs   1.45 s
    ✔ (uses native Rust) -computePayloadTimelinessCommitteeForSlot - 2    3711.374 ops/s    269.4420 us/op   x1.121       1229 runs  0.993 s
    ✔ naive TS - naiveComputePayloadTimelinessCommitteeForSlot - 10000    519.5736 ops/s    1.924655 ms/op   x1.230        211 runs   1.12 s
    ✔ (uses native Rust) -computePayloadTimelinessCommitteeForSlot - 1    1230.998 ops/s    812.3490 us/op   x1.286        535 runs   1.11 s

  computePayloadTimelinessCommitteesForEpoch - pure TS vs  Rust magic (250k -1M validators)
    ✔ naive TS - naiveComputePayloadTimelinessCommitteesForEpoch - 250    26.56509 ops/s    37.64339 ms/op   x1.035         10 runs  0.907 s
    ✔ (uses native Rust) -computePayloadTimelinessCommitteesForEpoch -    1063.618 ops/s    940.1870 us/op   x1.339        605 runs   1.48 s
    ✔ naive TS - naiveComputePayloadTimelinessCommitteesForEpoch - 100    25.44836 ops/s    39.29526 ms/op   x1.071         10 runs  0.937 s
    ✔ (uses native Rust) -computePayloadTimelinessCommitteesForEpoch -    1119.058 ops/s    893.6090 us/op   x1.251       1025 runs   1.99 s

AI Assistance Disclosure

Claude code was used for perf harness and wiring.

@guha-rahul guha-rahul requested a review from a team as a code owner April 23, 2026 16:30
Copy link
Copy Markdown
Contributor

@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 introduces optimized, Rust-backed implementations for Payload Timeliness Committee (PTC) computations by integrating new functions from the @chainsafe/swap-or-not-shuffle package. The existing JS implementations have been renamed to "naive" versions and are now used for verification in new performance benchmarks. Feedback includes concerns regarding the use of a local tarball dependency which breaks cross-platform support and CI builds, a suggestion to use the assert utility for error handling consistency, and a request to remove debug logging from the test suite.

"@chainsafe/pubkey-index-map": "^3.0.0",
"@chainsafe/ssz": "^1.4.0",
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
"@chainsafe/swap-or-not-shuffle": "file:../../chainsafe-swap-or-not-shuffle-1.2.1-local.tgz",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The use of a local tarball dependency (file:../../...) is problematic for shared repositories as it breaks builds for other developers and CI environments that do not have the file at that specific relative path. Furthermore, the pnpm-lock.yaml changes indicate that several supported platforms (e.g., darwin-x64, linux-x64-gnu) have been removed and versions for native bindings have been downgraded to 0.0.2. This dependency should be properly published to a registry or integrated via workspace references to maintain repository integrity and cross-platform support.

Comment on lines +326 to +328
if (shuffling.length === 0) {
throw Error("Validator indices must not be empty");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use the assert utility for consistency with other validation checks in this file and the Lodestar codebase.

  assert(shuffling.length > 0, "Validator indices must not be empty");

Comment on lines +127 to +128
// eslint-disable-next-line no-console
console.log(`[vc=${vc}] effectiveBalanceIncrements[0]=${effectiveBalanceIncrements[0]}`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Remove debug console.log and the associated eslint disable comment before merging.

Comment on lines +128 to +151
console.log(`[vc=${vc}] effectiveBalanceIncrements[0]=${effectiveBalanceIncrements[0]}`);

const naiveResult = naiveComputePayloadTimelinessCommitteesForEpoch(
cachedState,
epoch,
epochCtx.currentShuffling.committees,
effectiveBalanceIncrements
);
const rustResult = computePayloadTimelinessCommitteesForEpoch(
cachedState,
epoch,
epochCtx.currentShuffling,
effectiveBalanceIncrements
);
for (let i = 0; i < naiveResult.length; i++) {
const naive = naiveResult[i];
const rust = rustResult[i];
if (naive.length !== rust.length) {
throw new Error(`PTC length mismatch at slot ${i} (vc=${vc}): naive=${naive.length} rust=${rust.length}`);
}
for (let j = 0; j < naive.length; j++) {
if (naive[j] !== rust[j]) {
throw new Error(
`PTC index mismatch at slot ${i} position ${j} (vc=${vc}): naive=${naive[j]} rust=${rust[j]}`
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this should be removed, added this just to check the values from rust and native values

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.

1 participant