Skip to content

Conversation

@twoeths
Copy link
Contributor

@twoeths twoeths commented Dec 3, 2025

Motivation

Description

  • remove benchmarks for flow that's not used in prod
  • remove some "minMs" option for some tests that causes a lot of time
  • remote test that does not reflect the bottle neck of lodestar's performance as of Dec 2025
  • remote tests that's not part of lodestar code. It's only meaningful in the scope of that PR only

this is based on the long running test I found in https://github.com/ChainSafe/lodestar/actions/runs/19874295397/job/56957698411

packages/beacon-node/test/perf/chain/validation/attestation.test.ts
  validate gossip attestation
    ✔ batch validate gossip attestation - vc 640000 - chunk 32            8931.657 ops/s    111.9613 us/op   x0.918       7814 runs   30.0 s
    ✔ batch validate gossip attestation - vc 640000 - chunk 64            9972.473 ops/s    100.2760 us/op   x0.926       4321 runs   30.1 s
    ✔ batch validate gossip attestation - vc 640000 - chunk 128           10569.62 ops/s    94.61075 us/op   x0.921       2268 runs   30.0 s
    ✔ batch validate gossip attestation - vc 640000 - chunk 256           10069.74 ops/s    99.30746 us/op   x0.901       1154 runs   30.1 s

packages/fork-choice/test/perf/protoArray/computeDeltas.test.ts
  computeDeltas
    ✔ computeDeltas 1400000 validators 0% inactive                        73.51301 ops/s    13.60303 ms/op   x0.986        539 runs   10.0 s
    ✔ computeDeltas 1400000 validators 10% inactive                       78.91095 ops/s    12.67251 ms/op   x0.989        556 runs   10.0 s
    ✔ computeDeltas 1400000 validators 20% inactive                       86.73608 ops/s    11.52923 ms/op   x1.001        598 runs   10.0 s
    ✔ computeDeltas 1400000 validators 50% inactive                       114.8443 ops/s    8.707439 ms/op   x0.990        799 runs   10.0 s
    ✔ computeDeltas 2100000 validators 0% inactive                        48.69939 ops/s    20.53414 ms/op   x0.996        371 runs   10.0 s
    ✔ computeDeltas 2100000 validators 10% inactive                       53.13929 ops/s    18.81847 ms/op   x1.000        371 runs   10.0 s
    ✔ computeDeltas 2100000 validators 20% inactive                       60.11017 ops/s    16.63612 ms/op   x0.978        418 runs   10.0 s
    ✔ computeDeltas 2100000 validators 50% inactive                       79.46802 ops/s    12.58368 ms/op   x0.967        552 runs   10.0 s

packages/state-transition/test/perf/util/loadState/findModifiedValidators.test.ts
  find modified validators by different ways
    serialize validators then findModifiedValidators
      ✔ findModifiedValidators - 10000 modified validators                  1.382729 ops/s    723.2076 ms/op   x0.993         10 runs   9.21 s
      ✔ findModifiedValidators - 1000 modified validators                   1.298120 ops/s    770.3450 ms/op   x1.152         10 runs   8.68 s
      ✔ findModifiedValidators - 100 modified validators                    3.535168 ops/s    282.8720 ms/op   x1.329         10 runs   3.85 s
      ✔ findModifiedValidators - 10 modified validators                     4.648368 ops/s    215.1293 ms/op   x1.548         10 runs   3.13 s
      ✔ findModifiedValidators - 1 modified validators                      5.296754 ops/s    188.7949 ms/op   x1.187         10 runs   3.10 s
      ✔ findModifiedValidators - no difference                              3.873496 ops/s    258.1647 ms/op   x1.236         12 runs   3.88 s
    deserialize validators then compare validator ViewDUs
      ✔ compare ViewDUs                                                    0.1524038 ops/s    6.561514  s/op   x1.077          9 runs   65.7 s
    serialize each validator then compare Uin8Array
      ✔ compare each validator Uint8Array                                  0.8007866 ops/s    1.248772  s/op   x0.830         10 runs   13.7 s
    compare validator ViewDU to Uint8Array
      ✔ compare ViewDU to Uint8Array                                       0.9549799 ops/s    1.047143  s/op   x0.999         10 runs   11.5 s

packages/state-transition/test/perf/util/loadState/loadState.test.ts
  loadState
    ✔ migrate state 1000000 validators, 24 modified, 0 new               0.9790753 ops/s    1.021372  s/op   x1.147         57 runs   60.1 s
    ✔ migrate state 1000000 validators, 1700 modified, 1000 new          0.7290797 ops/s    1.371592  s/op   x0.942         43 runs   61.1 s
    ✔ migrate state 1000000 validators, 3400 modified, 2000 new          0.6307866 ops/s    1.585322  s/op   x0.883         37 runs   60.9 s
    ✔ migrate state 1500000 validators, 24 modified, 0 new               0.9393088 ops/s    1.064613  s/op   x0.911         55 runs   60.5 s
    ✔ migrate state 1500000 validators, 1700 modified, 1000 new          0.8235204 ops/s    1.214299  s/op   x0.785         48 runs   60.2 s
    ✔ migrate state 1500000 validators, 3400 modified, 2000 new          0.6997867 ops/s    1.429007  s/op   x0.720         41 runs   60.7 s


  ✔ naive computeProposerIndex 100000 validators                        21.29210 ops/s    46.96578 ms/op   x0.591         10 runs   51.8 s

  getNextSyncCommitteeIndices electra
    ✔ naiveGetNextSyncCommitteeIndices 1000 validators                   0.1319639 ops/s    7.577831  s/op   x0.675          8 runs   66.8 s
    ✔ getNextSyncCommitteeIndices 1000 validators                         9.444554 ops/s    105.8811 ms/op   x0.753         10 runs   1.60 s
    ✔ naiveGetNextSyncCommitteeIndices 10000 validators                  0.1280431 ops/s    7.809868  s/op   x0.766          7 runs   61.8 s
    ✔ getNextSyncCommitteeIndices 10000 validators                        9.244910 ops/s    108.1676 ms/op   x0.880         10 runs   1.62 s
    ✔ naiveGetNextSyncCommitteeIndices 100000 validators                 0.1295493 ops/s    7.719071  s/op   x0.814          7 runs   61.9 s
    ✔ getNextSyncCommitteeIndices 100000 validators                       9.279165 ops/s    107.7683 ms/op   x0.751         10 runs   1.62 s

  computeShuffledIndex
    ✔ naive computeShuffledIndex 100000 validators                      0.04376956 ops/s    22.84693  s/op   x0.719          2 runs   67.8 s
    ✔ cached computeShuffledIndex 100000 validators                       1.790556 ops/s    558.4858 ms/op   x0.973         10 runs   6.16 s
    ✔ naive computeShuffledIndex 2000000 validators                    0.002243157 ops/s    445.8003  s/op   x0.922          1 runs    931 s
    ✔ cached computeShuffledIndex 2000000 validators                    0.02947726 ops/s    33.92445  s/op   x0.810          1 runs   71.3 s

packages/state-transition/test/perf/util/signingRoot.test.ts
  computeSigningRoot
    ✔ computeSigningRoot for AttestationData                              51551.61 ops/s    19.39804 us/op   x0.905        491 runs   10.0 s
    ✔ hash AttestationData serialized data then Buffer.toString(base64    639269.7 ops/s    1.564285 us/op   x0.977       5818 runs   10.0 s
    ✔ toHexString serialized data                                         886487.9 ops/s    1.128047 us/op   x0.926       8417 runs   10.0 s
    ✔ Buffer.toString(base64)                                              6071166 ops/s    164.7130 ns/op   x0.974      50685 runs   10.1 s

@twoeths twoeths requested a review from a team as a code owner December 3, 2025 04:01
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @twoeths, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on improving the efficiency and relevance of the project's benchmark suite. By strategically removing outdated or non-critical tests and optimizing test configurations, the changes aim to reduce overall benchmark execution time, mitigate Out-Of-Memory errors, and ensure that the remaining benchmarks accurately reflect current production performance concerns.

Highlights

  • Benchmark Optimization: Significantly reduced benchmark execution time by removing non-essential tests and configurations.
  • Memory Management: Addressed Out-Of-Memory (OOM) issues observed with NodeJS 24 during benchmark runs.
  • Test Scope Refinement: Eliminated benchmarks for code paths not used in production and tests that no longer reflect current performance bottlenecks.
  • Configuration Streamlining: Removed the 'minMs' option from several benchmark configurations, which previously enforced minimum run times.
  • Deprecated Test Removal: Completely removed the 'signingRoot.test.ts' benchmark file, as it is no longer relevant.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
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 focuses on improving the performance and relevance of the benchmark suite. The changes effectively reduce benchmark execution time by removing fixed minimum run times (minMs), skipping slower or less relevant test suites, and removing a benchmark file that is no longer needed. Additionally, a minor but useful optimization is included to avoid an unnecessary array copy. The changes are well-aligned with the goal of making the benchmarks faster and more focused. I have one minor suggestion to fix a typo in a comment for better clarity.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 9fdee63 Previous: 548d7aa Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 892.44 us/op 930.42 us/op 0.96
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 33.871 us/op 36.236 us/op 0.93
BLS verify - blst 1.0659 ms/op 867.99 us/op 1.23
BLS verifyMultipleSignatures 3 - blst 1.6042 ms/op 1.3086 ms/op 1.23
BLS verifyMultipleSignatures 8 - blst 2.5001 ms/op 1.9669 ms/op 1.27
BLS verifyMultipleSignatures 32 - blst 7.4098 ms/op 4.9972 ms/op 1.48
BLS verifyMultipleSignatures 64 - blst 10.499 ms/op 9.8835 ms/op 1.06
BLS verifyMultipleSignatures 128 - blst 17.006 ms/op 17.016 ms/op 1.00
BLS deserializing 10000 signatures 663.98 ms/op 697.03 ms/op 0.95
BLS deserializing 100000 signatures 6.7168 s/op 7.0000 s/op 0.96
BLS verifyMultipleSignatures - same message - 3 - blst 881.96 us/op 973.61 us/op 0.91
BLS verifyMultipleSignatures - same message - 8 - blst 1.8566 ms/op 1.0901 ms/op 1.70
BLS verifyMultipleSignatures - same message - 32 - blst 1.6255 ms/op 1.7495 ms/op 0.93
BLS verifyMultipleSignatures - same message - 64 - blst 2.4980 ms/op 2.6695 ms/op 0.94
BLS verifyMultipleSignatures - same message - 128 - blst 4.2528 ms/op 4.4582 ms/op 0.95
BLS aggregatePubkeys 32 - blst 18.924 us/op 19.749 us/op 0.96
BLS aggregatePubkeys 128 - blst 67.435 us/op 71.079 us/op 0.95
notSeenSlots=1 numMissedVotes=1 numBadVotes=10 62.325 ms/op 51.693 ms/op 1.21
notSeenSlots=1 numMissedVotes=0 numBadVotes=4 43.289 ms/op 49.032 ms/op 0.88
notSeenSlots=2 numMissedVotes=1 numBadVotes=10 45.859 ms/op 38.568 ms/op 1.19
getSlashingsAndExits - default max 67.315 us/op 73.504 us/op 0.92
getSlashingsAndExits - 2k 298.44 us/op 367.92 us/op 0.81
isKnown best case - 1 super set check 194.00 ns/op 206.00 ns/op 0.94
isKnown normal case - 2 super set checks 190.00 ns/op 202.00 ns/op 0.94
isKnown worse case - 16 super set checks 192.00 ns/op 202.00 ns/op 0.95
InMemoryCheckpointStateCache - add get delete 2.3740 us/op 2.3890 us/op 0.99
validate api signedAggregateAndProof - struct 2.5927 ms/op 1.4865 ms/op 1.74
validate gossip signedAggregateAndProof - struct 1.7655 ms/op 1.4470 ms/op 1.22
batch validate gossip attestation - vc 640000 - chunk 32 115.00 us/op 122.01 us/op 0.94
batch validate gossip attestation - vc 640000 - chunk 64 100.12 us/op 108.23 us/op 0.93
batch validate gossip attestation - vc 640000 - chunk 128 94.502 us/op 102.72 us/op 0.92
batch validate gossip attestation - vc 640000 - chunk 256 105.53 us/op 110.17 us/op 0.96
pickEth1Vote - no votes 939.82 us/op 980.74 us/op 0.96
pickEth1Vote - max votes 6.8572 ms/op 7.7709 ms/op 0.88
pickEth1Vote - Eth1Data hashTreeRoot value x2048 12.242 ms/op 13.349 ms/op 0.92
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 21.750 ms/op 19.900 ms/op 1.09
pickEth1Vote - Eth1Data fastSerialize value x2048 427.22 us/op 433.52 us/op 0.99
pickEth1Vote - Eth1Data fastSerialize tree x2048 3.9570 ms/op 2.4563 ms/op 1.61
bytes32 toHexString 342.00 ns/op 373.00 ns/op 0.92
bytes32 Buffer.toString(hex) 235.00 ns/op 247.00 ns/op 0.95
bytes32 Buffer.toString(hex) from Uint8Array 313.00 ns/op 336.00 ns/op 0.93
bytes32 Buffer.toString(hex) + 0x 232.00 ns/op 249.00 ns/op 0.93
Object access 1 prop 0.11100 ns/op 0.12500 ns/op 0.89
Map access 1 prop 0.11700 ns/op 0.13400 ns/op 0.87
Object get x1000 5.5620 ns/op 5.8220 ns/op 0.96
Map get x1000 6.0540 ns/op 6.5170 ns/op 0.93
Object set x1000 27.378 ns/op 31.877 ns/op 0.86
Map set x1000 18.871 ns/op 21.298 ns/op 0.89
Return object 10000 times 0.28260 ns/op 0.29410 ns/op 0.96
Throw Error 10000 times 4.2631 us/op 4.3822 us/op 0.97
toHex 131.55 ns/op 140.82 ns/op 0.93
Buffer.from 120.50 ns/op 127.75 ns/op 0.94
shared Buffer 79.282 ns/op 88.892 ns/op 0.89
fastMsgIdFn sha256 / 200 bytes 2.1280 us/op 2.2150 us/op 0.96
fastMsgIdFn h32 xxhash / 200 bytes 202.00 ns/op 203.00 ns/op 1.00
fastMsgIdFn h64 xxhash / 200 bytes 266.00 ns/op 262.00 ns/op 1.02
fastMsgIdFn sha256 / 1000 bytes 6.9990 us/op 7.4480 us/op 0.94
fastMsgIdFn h32 xxhash / 1000 bytes 328.00 ns/op 342.00 ns/op 0.96
fastMsgIdFn h64 xxhash / 1000 bytes 364.00 ns/op 339.00 ns/op 1.07
fastMsgIdFn sha256 / 10000 bytes 63.310 us/op 66.840 us/op 0.95
fastMsgIdFn h32 xxhash / 10000 bytes 1.9110 us/op 1.8390 us/op 1.04
fastMsgIdFn h64 xxhash / 10000 bytes 1.1880 us/op 1.2170 us/op 0.98
100 bytes - compress - snappyjs 1.4505 us/op 1.5388 us/op 0.94
100 bytes - compress - snappy 1.0400 us/op 1.1514 us/op 0.90
200 bytes - compress - snappyjs 1.6712 us/op 1.9755 us/op 0.85
200 bytes - compress - snappy 1.1646 us/op 1.3096 us/op 0.89
300 bytes - compress - snappyjs 2.1825 us/op 2.9092 us/op 0.75
300 bytes - compress - snappy 1.2327 us/op 1.3695 us/op 0.90
400 bytes - compress - snappyjs 2.3518 us/op 3.1368 us/op 0.75
400 bytes - compress - snappy 1.3424 us/op 1.3746 us/op 0.98
500 bytes - compress - snappyjs 2.8275 us/op 3.2497 us/op 0.87
500 bytes - compress - snappy 1.2834 us/op 1.4557 us/op 0.88
1000 bytes - compress - snappyjs 4.5086 us/op 4.4018 us/op 1.02
1000 bytes - compress - snappy 1.4689 us/op 1.9490 us/op 0.75
10000 bytes - compress - snappyjs 29.328 us/op 33.173 us/op 0.88
10000 bytes - compress - snappy 30.923 us/op 41.044 us/op 0.75
100 bytes - uncompress - snappyjs 1.1025 us/op 1.2104 us/op 0.91
100 bytes - uncompress - snappy 1.0205 us/op 1.1073 us/op 0.92
200 bytes - uncompress - snappyjs 1.1407 us/op 1.6762 us/op 0.68
200 bytes - uncompress - snappy 1.2409 us/op 1.0698 us/op 1.16
300 bytes - uncompress - snappyjs 1.5361 us/op 1.4565 us/op 1.05
300 bytes - uncompress - snappy 1.0360 us/op 1.1131 us/op 0.93
400 bytes - uncompress - snappyjs 1.4883 us/op 1.5967 us/op 0.93
400 bytes - uncompress - snappy 1.1160 us/op 1.2693 us/op 0.88
500 bytes - uncompress - snappyjs 1.6868 us/op 1.8874 us/op 0.89
500 bytes - uncompress - snappy 1.0717 us/op 1.2474 us/op 0.86
1000 bytes - uncompress - snappyjs 2.7031 us/op 2.7853 us/op 0.97
1000 bytes - uncompress - snappy 1.3601 us/op 1.5457 us/op 0.88
10000 bytes - uncompress - snappyjs 13.327 us/op 14.725 us/op 0.91
10000 bytes - uncompress - snappy 29.356 us/op 30.164 us/op 0.97
send data - 1000 256B messages 14.919 ms/op 17.988 ms/op 0.83
send data - 1000 512B messages 18.240 ms/op 22.664 ms/op 0.80
send data - 1000 1024B messages 25.919 ms/op 32.989 ms/op 0.79
send data - 1000 1200B messages 27.412 ms/op 32.566 ms/op 0.84
send data - 1000 2048B messages 27.846 ms/op 28.950 ms/op 0.96
send data - 1000 4096B messages 28.524 ms/op 34.075 ms/op 0.84
send data - 1000 16384B messages 43.379 ms/op 51.049 ms/op 0.85
send data - 1000 65536B messages 107.86 ms/op 119.80 ms/op 0.90
enrSubnets - fastDeserialize 64 bits 902.00 ns/op 901.00 ns/op 1.00
enrSubnets - ssz BitVector 64 bits 327.00 ns/op 331.00 ns/op 0.99
enrSubnets - fastDeserialize 4 bits 129.00 ns/op 126.00 ns/op 1.02
enrSubnets - ssz BitVector 4 bits 326.00 ns/op 333.00 ns/op 0.98
prioritizePeers score -10:0 att 32-0.1 sync 2-0 231.56 us/op 238.96 us/op 0.97
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 254.58 us/op 268.03 us/op 0.95
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 369.75 us/op 392.07 us/op 0.94
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 697.85 us/op 726.23 us/op 0.96
prioritizePeers score 0:0 att 64-1 sync 4-1 831.69 us/op 874.15 us/op 0.95
array of 16000 items push then shift 1.5837 us/op 1.6738 us/op 0.95
LinkedList of 16000 items push then shift 7.0810 ns/op 7.5640 ns/op 0.94
array of 16000 items push then pop 73.245 ns/op 84.294 ns/op 0.87
LinkedList of 16000 items push then pop 7.0500 ns/op 8.0060 ns/op 0.88
array of 24000 items push then shift 2.3503 us/op 2.3882 us/op 0.98
LinkedList of 24000 items push then shift 7.1430 ns/op 7.5790 ns/op 0.94
array of 24000 items push then pop 97.905 ns/op 111.10 ns/op 0.88
LinkedList of 24000 items push then pop 6.8140 ns/op 8.5430 ns/op 0.80
intersect bitArray bitLen 8 6.1210 ns/op 6.4600 ns/op 0.95
intersect array and set length 8 35.833 ns/op 37.644 ns/op 0.95
intersect bitArray bitLen 128 28.235 ns/op 29.570 ns/op 0.95
intersect array and set length 128 587.66 ns/op 627.74 ns/op 0.94
bitArray.getTrueBitIndexes() bitLen 128 938.00 ns/op 1.0170 us/op 0.92
bitArray.getTrueBitIndexes() bitLen 248 1.6780 us/op 1.7850 us/op 0.94
bitArray.getTrueBitIndexes() bitLen 512 3.5280 us/op 3.7850 us/op 0.93
Full columns - reconstruct all 6 blobs 74.931 us/op 112.83 us/op 0.66
Full columns - reconstruct half of the blobs out of 6 41.016 us/op 44.118 us/op 0.93
Full columns - reconstruct single blob out of 6 18.085 us/op 20.005 us/op 0.90
Half columns - reconstruct all 6 blobs 264.18 ms/op 279.40 ms/op 0.95
Half columns - reconstruct half of the blobs out of 6 129.79 ms/op 137.91 ms/op 0.94
Half columns - reconstruct single blob out of 6 46.947 ms/op 57.368 ms/op 0.82
Full columns - reconstruct all 10 blobs 97.749 us/op 153.69 us/op 0.64
Full columns - reconstruct half of the blobs out of 10 53.318 us/op 72.639 us/op 0.73
Full columns - reconstruct single blob out of 10 17.361 us/op 21.622 us/op 0.80
Half columns - reconstruct all 10 blobs 432.97 ms/op 488.60 ms/op 0.89
Half columns - reconstruct half of the blobs out of 10 218.93 ms/op 243.56 ms/op 0.90
Half columns - reconstruct single blob out of 10 47.632 ms/op 51.053 ms/op 0.93
Full columns - reconstruct all 20 blobs 202.45 us/op 301.38 us/op 0.67
Full columns - reconstruct half of the blobs out of 20 99.497 us/op 145.38 us/op 0.68
Full columns - reconstruct single blob out of 20 16.527 us/op 21.550 us/op 0.77
Half columns - reconstruct all 20 blobs 857.51 ms/op 907.67 ms/op 0.94
Half columns - reconstruct half of the blobs out of 20 430.14 ms/op 460.94 ms/op 0.93
Half columns - reconstruct single blob out of 20 48.088 ms/op 51.574 ms/op 0.93
Set add up to 64 items then delete first 2.0554 us/op 2.3611 us/op 0.87
OrderedSet add up to 64 items then delete first 3.0999 us/op 3.3344 us/op 0.93
Set add up to 64 items then delete last 2.1415 us/op 2.5730 us/op 0.83
OrderedSet add up to 64 items then delete last 3.8388 us/op 4.2142 us/op 0.91
Set add up to 64 items then delete middle 2.4942 us/op 2.8116 us/op 0.89
OrderedSet add up to 64 items then delete middle 5.5726 us/op 6.2742 us/op 0.89
Set add up to 128 items then delete first 4.7655 us/op 5.7595 us/op 0.83
OrderedSet add up to 128 items then delete first 7.2125 us/op 8.9823 us/op 0.80
Set add up to 128 items then delete last 4.8644 us/op 5.3006 us/op 0.92
OrderedSet add up to 128 items then delete last 7.4568 us/op 8.8718 us/op 0.84
Set add up to 128 items then delete middle 4.6995 us/op 5.3215 us/op 0.88
OrderedSet add up to 128 items then delete middle 13.696 us/op 14.919 us/op 0.92
Set add up to 256 items then delete first 10.186 us/op 11.655 us/op 0.87
OrderedSet add up to 256 items then delete first 14.874 us/op 16.590 us/op 0.90
Set add up to 256 items then delete last 9.5386 us/op 10.198 us/op 0.94
OrderedSet add up to 256 items then delete last 14.752 us/op 15.086 us/op 0.98
Set add up to 256 items then delete middle 9.5252 us/op 9.4703 us/op 1.01
OrderedSet add up to 256 items then delete middle 41.017 us/op 43.032 us/op 0.95
pass gossip attestations to forkchoice per slot 2.5707 ms/op 2.7269 ms/op 0.94
forkChoice updateHead vc 100000 bc 64 eq 0 454.42 us/op 471.24 us/op 0.96
forkChoice updateHead vc 600000 bc 64 eq 0 2.7782 ms/op 2.8099 ms/op 0.99
forkChoice updateHead vc 1000000 bc 64 eq 0 4.6555 ms/op 4.6809 ms/op 0.99
forkChoice updateHead vc 600000 bc 320 eq 0 2.7797 ms/op 2.8330 ms/op 0.98
forkChoice updateHead vc 600000 bc 1200 eq 0 2.8300 ms/op 2.8651 ms/op 0.99
forkChoice updateHead vc 600000 bc 7200 eq 0 3.1589 ms/op 3.1782 ms/op 0.99
forkChoice updateHead vc 600000 bc 64 eq 1000 2.8032 ms/op 2.9129 ms/op 0.96
forkChoice updateHead vc 600000 bc 64 eq 10000 2.9156 ms/op 3.0470 ms/op 0.96
forkChoice updateHead vc 600000 bc 64 eq 300000 9.5135 ms/op 9.5957 ms/op 0.99
computeDeltas 1400000 validators 0% inactive 13.523 ms/op 13.791 ms/op 0.98
computeDeltas 1400000 validators 10% inactive 12.559 ms/op 12.810 ms/op 0.98
computeDeltas 1400000 validators 20% inactive 11.367 ms/op 11.513 ms/op 0.99
computeDeltas 1400000 validators 50% inactive 8.6085 ms/op 8.7964 ms/op 0.98
computeDeltas 2100000 validators 0% inactive 20.259 ms/op 20.615 ms/op 0.98
computeDeltas 2100000 validators 10% inactive 18.843 ms/op 18.817 ms/op 1.00
computeDeltas 2100000 validators 20% inactive 17.051 ms/op 17.006 ms/op 1.00
computeDeltas 2100000 validators 50% inactive 12.920 ms/op 13.015 ms/op 0.99
altair processAttestation - 250000 vs - 7PWei normalcase 1.9760 ms/op 2.0712 ms/op 0.95
altair processAttestation - 250000 vs - 7PWei worstcase 2.9561 ms/op 2.8745 ms/op 1.03
altair processAttestation - setStatus - 1/6 committees join 119.89 us/op 121.54 us/op 0.99
altair processAttestation - setStatus - 1/3 committees join 224.60 us/op 245.14 us/op 0.92
altair processAttestation - setStatus - 1/2 committees join 325.92 us/op 327.93 us/op 0.99
altair processAttestation - setStatus - 2/3 committees join 421.61 us/op 425.43 us/op 0.99
altair processAttestation - setStatus - 4/5 committees join 568.46 us/op 588.04 us/op 0.97
altair processAttestation - setStatus - 100% committees join 678.61 us/op 688.86 us/op 0.99
altair processBlock - 250000 vs - 7PWei normalcase 6.2659 ms/op 4.1833 ms/op 1.50
altair processBlock - 250000 vs - 7PWei normalcase hashState 29.982 ms/op 32.414 ms/op 0.92
altair processBlock - 250000 vs - 7PWei worstcase 40.600 ms/op 32.092 ms/op 1.27
altair processBlock - 250000 vs - 7PWei worstcase hashState 92.429 ms/op 67.404 ms/op 1.37
phase0 processBlock - 250000 vs - 7PWei normalcase 2.5398 ms/op 1.6079 ms/op 1.58
phase0 processBlock - 250000 vs - 7PWei worstcase 23.439 ms/op 21.154 ms/op 1.11
altair processEth1Data - 250000 vs - 7PWei normalcase 333.04 us/op 329.68 us/op 1.01
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 9.7050 us/op 6.4230 us/op 1.51
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 56.452 us/op 45.606 us/op 1.24
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 16.070 us/op 11.790 us/op 1.36
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 10.261 us/op 6.4040 us/op 1.60
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 245.24 us/op 146.44 us/op 1.67
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.7752 ms/op 1.8073 ms/op 0.98
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.2523 ms/op 2.3754 ms/op 0.95
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.1155 ms/op 2.2702 ms/op 0.93
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 4.4508 ms/op 4.6174 ms/op 0.96
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.3114 ms/op 2.3823 ms/op 0.97
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.3822 ms/op 4.5779 ms/op 0.96
Tree 40 250000 create 397.78 ms/op 427.18 ms/op 0.93
Tree 40 250000 get(125000) 133.27 ns/op 135.06 ns/op 0.99
Tree 40 250000 set(125000) 1.4525 us/op 1.4687 us/op 0.99
Tree 40 250000 toArray() 14.835 ms/op 15.538 ms/op 0.95
Tree 40 250000 iterate all - toArray() + loop 16.277 ms/op 15.381 ms/op 1.06
Tree 40 250000 iterate all - get(i) 49.494 ms/op 49.062 ms/op 1.01
Array 250000 create 2.7700 ms/op 3.6792 ms/op 0.75
Array 250000 clone - spread 779.28 us/op 784.59 us/op 0.99
Array 250000 get(125000) 0.53100 ns/op 0.40600 ns/op 1.31
Array 250000 set(125000) 0.41200 ns/op 0.43000 ns/op 0.96
Array 250000 iterate all - loop 97.641 us/op 100.67 us/op 0.97
phase0 afterProcessEpoch - 250000 vs - 7PWei 40.024 ms/op 39.972 ms/op 1.00
Array.fill - length 1000000 3.4845 ms/op 3.2827 ms/op 1.06
Array push - length 1000000 16.538 ms/op 13.586 ms/op 1.22
Array.get 0.26167 ns/op 0.27835 ns/op 0.94
Uint8Array.get 0.42210 ns/op 0.43404 ns/op 0.97
phase0 beforeProcessEpoch - 250000 vs - 7PWei 15.950 ms/op 16.106 ms/op 0.99
altair processEpoch - mainnet_e81889 285.23 ms/op 278.45 ms/op 1.02
mainnet_e81889 - altair beforeProcessEpoch 17.114 ms/op 18.917 ms/op 0.90
mainnet_e81889 - altair processJustificationAndFinalization 5.5550 us/op 5.4360 us/op 1.02
mainnet_e81889 - altair processInactivityUpdates 4.0608 ms/op 4.2138 ms/op 0.96
mainnet_e81889 - altair processRewardsAndPenalties 49.526 ms/op 37.470 ms/op 1.32
mainnet_e81889 - altair processRegistryUpdates 682.00 ns/op 651.00 ns/op 1.05
mainnet_e81889 - altair processSlashings 176.00 ns/op 180.00 ns/op 0.98
mainnet_e81889 - altair processEth1DataReset 171.00 ns/op 175.00 ns/op 0.98
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.1885 ms/op 1.2018 ms/op 0.99
mainnet_e81889 - altair processSlashingsReset 1.0070 us/op 832.00 ns/op 1.21
mainnet_e81889 - altair processRandaoMixesReset 1.1600 us/op 1.0900 us/op 1.06
mainnet_e81889 - altair processHistoricalRootsUpdate 182.00 ns/op 174.00 ns/op 1.05
mainnet_e81889 - altair processParticipationFlagUpdates 513.00 ns/op 503.00 ns/op 1.02
mainnet_e81889 - altair processSyncCommitteeUpdates 135.00 ns/op 141.00 ns/op 0.96
mainnet_e81889 - altair afterProcessEpoch 43.266 ms/op 43.873 ms/op 0.99
capella processEpoch - mainnet_e217614 1.0140 s/op 831.10 ms/op 1.22
mainnet_e217614 - capella beforeProcessEpoch 61.868 ms/op 60.844 ms/op 1.02
mainnet_e217614 - capella processJustificationAndFinalization 7.0290 us/op 5.1700 us/op 1.36
mainnet_e217614 - capella processInactivityUpdates 13.965 ms/op 14.075 ms/op 0.99
mainnet_e217614 - capella processRewardsAndPenalties 198.64 ms/op 175.72 ms/op 1.13
mainnet_e217614 - capella processRegistryUpdates 11.702 us/op 6.2760 us/op 1.86
mainnet_e217614 - capella processSlashings 177.00 ns/op 173.00 ns/op 1.02
mainnet_e217614 - capella processEth1DataReset 192.00 ns/op 172.00 ns/op 1.12
mainnet_e217614 - capella processEffectiveBalanceUpdates 4.1313 ms/op 10.310 ms/op 0.40
mainnet_e217614 - capella processSlashingsReset 1.0360 us/op 858.00 ns/op 1.21
mainnet_e217614 - capella processRandaoMixesReset 1.1300 us/op 1.1130 us/op 1.02
mainnet_e217614 - capella processHistoricalRootsUpdate 172.00 ns/op 172.00 ns/op 1.00
mainnet_e217614 - capella processParticipationFlagUpdates 492.00 ns/op 517.00 ns/op 0.95
mainnet_e217614 - capella afterProcessEpoch 109.73 ms/op 112.62 ms/op 0.97
phase0 processEpoch - mainnet_e58758 304.09 ms/op 276.32 ms/op 1.10
mainnet_e58758 - phase0 beforeProcessEpoch 83.159 ms/op 73.257 ms/op 1.14
mainnet_e58758 - phase0 processJustificationAndFinalization 7.0200 us/op 5.5570 us/op 1.26
mainnet_e58758 - phase0 processRewardsAndPenalties 39.043 ms/op 39.694 ms/op 0.98
mainnet_e58758 - phase0 processRegistryUpdates 3.0510 us/op 3.1000 us/op 0.98
mainnet_e58758 - phase0 processSlashings 176.00 ns/op 178.00 ns/op 0.99
mainnet_e58758 - phase0 processEth1DataReset 178.00 ns/op 172.00 ns/op 1.03
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.1592 ms/op 1.1940 ms/op 0.97
mainnet_e58758 - phase0 processSlashingsReset 892.00 ns/op 935.00 ns/op 0.95
mainnet_e58758 - phase0 processRandaoMixesReset 1.3630 us/op 1.2050 us/op 1.13
mainnet_e58758 - phase0 processHistoricalRootsUpdate 169.00 ns/op 177.00 ns/op 0.95
mainnet_e58758 - phase0 processParticipationRecordUpdates 862.00 ns/op 891.00 ns/op 0.97
mainnet_e58758 - phase0 afterProcessEpoch 34.964 ms/op 41.204 ms/op 0.85
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.1937 ms/op 1.3691 ms/op 0.87
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 2.6974 ms/op 2.5541 ms/op 1.06
altair processInactivityUpdates - 250000 normalcase 19.297 ms/op 16.882 ms/op 1.14
altair processInactivityUpdates - 250000 worstcase 23.753 ms/op 18.353 ms/op 1.29
phase0 processRegistryUpdates - 250000 normalcase 9.0790 us/op 6.7410 us/op 1.35
phase0 processRegistryUpdates - 250000 badcase_full_deposits 320.17 us/op 255.95 us/op 1.25
phase0 processRegistryUpdates - 250000 worstcase 0.5 124.60 ms/op 96.545 ms/op 1.29
altair processRewardsAndPenalties - 250000 normalcase 29.608 ms/op 26.161 ms/op 1.13
altair processRewardsAndPenalties - 250000 worstcase 39.546 ms/op 25.134 ms/op 1.57
phase0 getAttestationDeltas - 250000 normalcase 6.9349 ms/op 6.8177 ms/op 1.02
phase0 getAttestationDeltas - 250000 worstcase 6.8740 ms/op 5.8273 ms/op 1.18
phase0 processSlashings - 250000 worstcase 94.585 us/op 85.852 us/op 1.10
altair processSyncCommitteeUpdates - 250000 10.473 ms/op 10.980 ms/op 0.95
BeaconState.hashTreeRoot - No change 215.00 ns/op 210.00 ns/op 1.02
BeaconState.hashTreeRoot - 1 full validator 86.605 us/op 97.167 us/op 0.89
BeaconState.hashTreeRoot - 32 full validator 1.2088 ms/op 775.74 us/op 1.56
BeaconState.hashTreeRoot - 512 full validator 10.339 ms/op 9.0847 ms/op 1.14
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 135.88 us/op 92.188 us/op 1.47
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.5356 ms/op 1.3500 ms/op 1.14
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 27.229 ms/op 22.820 ms/op 1.19
BeaconState.hashTreeRoot - 1 balances 90.103 us/op 74.885 us/op 1.20
BeaconState.hashTreeRoot - 32 balances 942.58 us/op 805.19 us/op 1.17
BeaconState.hashTreeRoot - 512 balances 8.1214 ms/op 8.2607 ms/op 0.98
BeaconState.hashTreeRoot - 250000 balances 198.22 ms/op 168.03 ms/op 1.18
aggregationBits - 2048 els - zipIndexesInBitList 21.017 us/op 21.714 us/op 0.97
regular array get 100000 times 43.137 us/op 42.507 us/op 1.01
wrappedArray get 100000 times 32.323 us/op 31.602 us/op 1.02
arrayWithProxy get 100000 times 12.765 ms/op 17.787 ms/op 0.72
ssz.Root.equals 45.742 ns/op 44.705 ns/op 1.02
byteArrayEquals 44.857 ns/op 43.852 ns/op 1.02
Buffer.compare 10.219 ns/op 10.072 ns/op 1.01
processSlot - 1 slots 10.430 us/op 10.122 us/op 1.03
processSlot - 32 slots 2.9517 ms/op 3.3013 ms/op 0.89
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 2.8513 ms/op 2.8532 ms/op 1.00
getCommitteeAssignments - req 1 vs - 250000 vc 2.1114 ms/op 2.0683 ms/op 1.02
getCommitteeAssignments - req 100 vs - 250000 vc 4.1012 ms/op 4.0247 ms/op 1.02
getCommitteeAssignments - req 1000 vs - 250000 vc 4.3747 ms/op 4.3005 ms/op 1.02
findModifiedValidators - 10000 modified validators 734.04 ms/op 728.18 ms/op 1.01
findModifiedValidators - 1000 modified validators 719.63 ms/op 668.63 ms/op 1.08
findModifiedValidators - 100 modified validators 266.47 ms/op 212.87 ms/op 1.25
findModifiedValidators - 10 modified validators 226.15 ms/op 139.00 ms/op 1.63
findModifiedValidators - 1 modified validators 197.80 ms/op 159.02 ms/op 1.24
findModifiedValidators - no difference 169.62 ms/op 208.95 ms/op 0.81
migrate state 1500000 validators, 3400 modified, 2000 new 1.4814 s/op 1.9849 s/op 0.75
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.0400 ns/op 4.4400 ns/op 0.91
state getBlockRootAtSlot - 250000 vs - 7PWei 575.76 ns/op 572.49 ns/op 1.01
computeProposerIndex 100000 validators 1.5278 ms/op 1.6447 ms/op 0.93
getNextSyncCommitteeIndices 1000 validators 114.39 ms/op 140.63 ms/op 0.81
getNextSyncCommitteeIndices 10000 validators 116.23 ms/op 122.97 ms/op 0.95
getNextSyncCommitteeIndices 100000 validators 115.57 ms/op 143.47 ms/op 0.81
computeProposers - vc 250000 616.52 us/op 760.07 us/op 0.81
computeEpochShuffling - vc 250000 41.247 ms/op 42.008 ms/op 0.98
getNextSyncCommittee - vc 250000 10.357 ms/op 10.535 ms/op 0.98
nodejs block root to RootHex using toHex 152.05 ns/op 152.79 ns/op 1.00
nodejs block root to RootHex using toRootHex 89.846 ns/op 87.425 ns/op 1.03
nodejs fromHex(blob) 107.06 us/op 120.97 us/op 0.88
nodejs fromHexInto(blob) 805.24 us/op 829.29 us/op 0.97
nodejs block root to RootHex using the deprecated toHexString 203.60 ns/op 218.28 ns/op 0.93
browser block root to RootHex using toHex 175.39 ns/op 176.33 ns/op 0.99
browser block root to RootHex using toRootHex 160.71 ns/op 166.35 ns/op 0.97
browser fromHex(blob) 772.13 us/op 799.93 us/op 0.97
browser fromHexInto(blob) 797.60 us/op 827.60 us/op 0.96
browser block root to RootHex using the deprecated toHexString 958.39 ns/op 837.78 ns/op 1.14

by benchmarkbot/action

@twoeths
Copy link
Contributor Author

twoeths commented Dec 3, 2025

benchmark execution time was cut down from ~50m to ~13m

@nflaig nflaig changed the title fix: improve benchmark chore: improve benchmark Dec 3, 2025
✔ toHexString serialized data 727592.3 ops/s 1.374396 us/op - 6916 runs 10.0 s
✔ Buffer.toString(base64) 2570800 ops/s 388.9840 ns/op - 24628 runs 10.1 s
*/
describe("computeSigningRoot", () => {
Copy link
Member

Choose a reason for hiding this comment

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

why was this removed instead of just skipped?

Copy link
Contributor Author

@twoeths twoeths Dec 3, 2025

Choose a reason for hiding this comment

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

as I remember computeSigningRoot() was the bottle neck when we verify attestations
things changed completely since we switch to verifying attestations in batch
it was more about knowing how much does it cause than maintaining its performance over time since the performance implementation is very simple
for clone() and Buffer.from(bytes).toString("base64");: it is what it is, there is nothing to improve there, we also don't want to manage benchmark for them.

@wemeetagain wemeetagain merged commit 1ad9c40 into unstable Dec 3, 2025
42 of 47 checks passed
@wemeetagain wemeetagain deleted the te/improve_benchmark branch December 3, 2025 14:57
@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.02%. Comparing base (548d7aa) to head (9959806).
⚠️ Report is 3 commits behind head on unstable.

Additional details and impacted files
@@            Coverage Diff            @@
##           unstable    #8664   +/-   ##
=========================================
  Coverage     52.02%   52.02%           
=========================================
  Files           848      848           
  Lines         65837    65837           
  Branches       4811     4811           
=========================================
  Hits          34250    34250           
  Misses        31518    31518           
  Partials         69       69           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@wemeetagain
Copy link
Member

🎉 This PR is included in v1.38.0 🎉

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.

4 participants