Skip to content

Conversation

wemeetagain
Copy link
Member

Motivation

Description

  • Add LmdbController -- uses the lmdb binding from lodestar-bun in bun, empty implementation in nodejs
  • Add --dbType hidden flag to select "level" | "lmdb"

@wemeetagain wemeetagain requested a review from a team as a code owner September 30, 2025 15:00
Copy link
Contributor

Summary of Changes

Hello @wemeetagain, 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 significantly enhances the database flexibility of the beacon node by integrating LMDB as an alternative to the existing LevelDB. The change introduces a new LmdbController that utilizes lodestar-bun bindings for Bun-based environments, while maintaining LevelDB support for Node.js. Users can now specify their preferred database type via a new, hidden command-line flag, enabling potential performance optimizations or compatibility improvements based on their runtime environment.

Highlights

  • LMDB Database Integration: Introduced LmdbController to support LMDB as an alternative database backend, specifically leveraging lodestar-bun for Bun environments. The Node.js implementation is currently a placeholder.
  • Configurable Database Type: Added a new hidden CLI flag --dbType allowing users to choose between "level" (LevelDB) and "lmdb" for their database backend.
  • Database Abstraction Updates: Modified various core components (ArchiveStore, HistoricalStateRegen, BeaconChain, BeaconNode) to accept and propagate the dbType option, ensuring the correct database controller is instantiated based on user selection.
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 introduces support for LMDB as a database backend, adding a --dbType flag to switch between LevelDB and LMDB. The changes primarily involve plumbing the new dbType option through various parts of the application and providing two implementations for LmdbController: a functional one for the Bun runtime and a stub for Node.js. The overall approach is solid. I've identified a typing issue in the Node.js stub and significant code duplication in the Bun implementation, for which I've provided suggestions to improve maintainability and correctness.

Comment on lines 151 to 407
keysStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<Uint8Array> {
const tx = transactionBegin(this.db);
const db = 0 as Database;

const iterator = databaseCursor(tx, db);

const metrics = this.metrics;
const bucket = opts.bucketId ?? BUCKET_ID_UNKNOWN;
metrics?.dbReadReq.inc({bucket}, 1);
let itemsRead = 0;

return (async function* () {
try {
if (opts.gt) {
cursorSeek(iterator, opts.gt);
const first = cursorGoToNext(iterator);
if (!first) return;
itemsRead++;
yield first.slice();
} else if (opts.gte) {
const first = cursorSeek(iterator, opts.gte);
if (!first) return;
itemsRead++;
yield first.slice();
} else {
const first = cursorGoToFirst(iterator);
if (!first) return;
itemsRead++;
yield first.slice();
}

while (true) {
const key = cursorGoToNext(iterator);
if (!key) return;
if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;
itemsRead++;
yield key.slice();
}
} finally {
metrics?.dbReadItems.inc({bucket}, itemsRead);
cursorDeinit(iterator);
transactionAbort(tx);
}
})();
}

async keys(opts: FilterOptions<Uint8Array> = {}): Promise<Uint8Array[]> {
const tx = transactionBegin(this.db);
const db = 0 as Database;
const iterator = databaseCursor(tx, db);
this.metrics?.dbReadReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
const keys: Uint8Array[] = [];
try {
if (opts.gt) {
cursorSeek(iterator, opts.gt);
const first = cursorGoToNext(iterator);
if (!first) return keys;
keys.push(first.slice());
} else if (opts.gte) {
const first = cursorSeek(iterator, opts.gte);
if (!first) return keys;
keys.push(first.slice());
} else {
const first = cursorGoToFirst(iterator);
if (!first) return keys;
keys.push(first.slice());
}
while (true) {
const key = cursorGoToNext(iterator);
if (!key) break;
if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;
keys.push(key.slice());
}
return keys;
} finally {
this.metrics?.dbReadItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, keys.length);
cursorDeinit(iterator);
transactionAbort(tx);
}
}

valuesStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<Uint8Array> {
const tx = transactionBegin(this.db);
const db = 0 as Database;
const iterator = databaseCursor(tx, db);
const bucket = opts.bucketId ?? BUCKET_ID_UNKNOWN;
const metrics = this.metrics;
metrics?.dbReadReq.inc({bucket}, 1);
let itemsRead = 0;
return (async function* () {
try {
if (opts.gt) {
cursorSeek(iterator, opts.gt);
const first = cursorGoToNext(iterator);
if (!first) return;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield value.slice();
} else if (opts.gte) {
const first = cursorSeek(iterator, opts.gte);
if (!first) return;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield value.slice();
} else {
const first = cursorGoToFirst(iterator);
if (!first) return;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield value.slice();
}
while (true) {
const key = cursorGoToNext(iterator);
if (!key) return;
if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield value.slice();
}
} finally {
metrics?.dbReadItems.inc({bucket}, itemsRead);
cursorDeinit(iterator);
transactionAbort(tx);
}
})();
}

async values(opts: FilterOptions<Uint8Array> = {}): Promise<Uint8Array[]> {
const tx = transactionBegin(this.db);
const db = 0 as Database;
const iterator = databaseCursor(tx, db);
const values: Uint8Array[] = [];
this.metrics?.dbReadReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
try {
if (opts.gt) {
cursorSeek(iterator, opts.gt);
const first = cursorGoToNext(iterator);
if (!first) return values;
const value = cursorGetCurrentValue(iterator);
values.push(value.slice());
} else if (opts.gte) {
const first = cursorSeek(iterator, opts.gte);
if (!first) return values;
const value = cursorGetCurrentValue(iterator);
values.push(value.slice());
} else {
const first = cursorGoToFirst(iterator);
if (!first) return values;
const value = cursorGetCurrentValue(iterator);
values.push(value.slice());
}
while (true) {
const key = cursorGoToNext(iterator);
if (!key) break;
if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;
const value = cursorGetCurrentValue(iterator);
values.push(value.slice());
}
return values;
} finally {
this.metrics?.dbReadItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, values.length);
cursorDeinit(iterator);
transactionAbort(tx);
}
}

entriesStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<KeyValue<Uint8Array, Uint8Array>> {
const tx = transactionBegin(this.db);
const db = 0 as Database;
const iterator = databaseCursor(tx, db);
const bucket = opts.bucketId ?? BUCKET_ID_UNKNOWN;
const metrics = this.metrics;
metrics?.dbReadReq.inc({bucket}, 1);
let itemsRead = 0;
return (async function* () {
try {
if (opts.gt) {
cursorSeek(iterator, opts.gt);
const first = cursorGoToNext(iterator);
if (!first) return;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield {key: first.slice(), value: value.slice()};
} else if (opts.gte) {
const first = cursorSeek(iterator, opts.gte);
if (!first) return;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield {key: first.slice(), value: value.slice()};
} else {
const first = cursorGoToFirst(iterator);
if (!first) return;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield {key: first.slice(), value: value.slice()};
}
while (true) {
const key = cursorGoToNext(iterator);
if (!key) return;
if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;
const value = cursorGetCurrentValue(iterator);
itemsRead++;
yield {key: key.slice(), value: value.slice()};
}
} finally {
metrics?.dbReadItems.inc({bucket}, itemsRead);
cursorDeinit(iterator);
transactionAbort(tx);
}
})();
}

async entries(opts: FilterOptions<Uint8Array> = {}): Promise<KeyValue<Uint8Array, Uint8Array>[]> {
const tx = transactionBegin(this.db);
const db = 0 as Database;
const iterator = databaseCursor(tx, db);
const entries: KeyValue<Uint8Array, Uint8Array>[] = [];
this.metrics?.dbReadReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
try {
if (opts.gt) {
cursorSeek(iterator, opts.gt);
const first = cursorGoToNext(iterator);
if (!first) return entries;
const value = cursorGetCurrentValue(iterator);
entries.push({key: first.slice(), value: value.slice()});
} else if (opts.gte) {
const first = cursorSeek(iterator, opts.gte);
if (!first) return entries;
const value = cursorGetCurrentValue(iterator);
entries.push({key: first.slice(), value: value.slice()});
} else {
const first = cursorGoToFirst(iterator);
if (!first) return entries;
const value = cursorGetCurrentValue(iterator);
entries.push({key: first.slice(), value: value.slice()});
}
while (true) {
const key = cursorGoToNext(iterator);
if (!key) break;
if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;
const value = cursorGetCurrentValue(iterator);
entries.push({key: key.slice(), value: value.slice()});
}
return entries;
} finally {
this.metrics?.dbReadItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, entries.length);
cursorDeinit(iterator);
transactionAbort(tx);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There is significant code duplication across the keys, values, entries methods and their ...Stream counterparts. This can be refactored to improve maintainability.

You could introduce two private helper methods:

  1. A private async generator _iterate to handle the core cursor logic and yield key-value pairs. The ...Stream methods can then wrap this generator to transform the output.
  2. A private _collect method that uses the same iteration logic to build and return an array. The keys, values, and entries methods can then use this helper.

This will centralize the iteration and filtering logic, making the code cleaner and easier to maintain.

  private async* _iterate(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<{key: Uint8Array; value: Uint8Array}> {
    const tx = transactionBegin(this.db);
    const db = 0 as Database;
    const iterator = databaseCursor(tx, db);
    const bucket = opts.bucketId ?? BUCKET_ID_UNKNOWN;
    const metrics = this.metrics;
    metrics?.dbReadReq.inc({bucket}, 1);
    let itemsRead = 0;

    try {
      let key: Uint8Array | null;

      if (opts.gt) {
        cursorSeek(iterator, opts.gt);
        key = cursorGoToNext(iterator);
      } else if (opts.gte) {
        key = cursorSeek(iterator, opts.gte);
      } else {
        key = cursorGoToFirst(iterator);
      }

      if (key) {
        do {
          if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
          if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;

          const value = cursorGetCurrentValue(iterator);
          itemsRead++;
          yield {key: key.slice(), value: value.slice()};
        } while ((key = cursorGoToNext(iterator)));
      }
    } finally {
      metrics?.dbReadItems.inc({bucket}, itemsRead);
      cursorDeinit(iterator);
      transactionAbort(tx);
    }
  }

  private async _collect<T>(
    opts: FilterOptions<Uint8Array> = {},
    transform: (key: Uint8Array, value: Uint8Array) => T
  ): Promise<T[]> {
    const tx = transactionBegin(this.db);
    const db = 0 as Database;
    const iterator = databaseCursor(tx, db);
    this.metrics?.dbReadReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
    const results: T[] = [];
    try {
      let key: Uint8Array | null;

      if (opts.gt) {
        cursorSeek(iterator, opts.gt);
        key = cursorGoToNext(iterator);
      } else if (opts.gte) {
        key = cursorSeek(iterator, opts.gte);
      } else {
        key = cursorGoToFirst(iterator);
      }

      if (key) {
        do {
          if (opts.lt && Buffer.compare(key, opts.lt) >= 0) break;
          if (opts.lte && Buffer.compare(key, opts.lte) > 0) break;

          const value = cursorGetCurrentValue(iterator);
          results.push(transform(key.slice(), value.slice()));
        } while ((key = cursorGoToNext(iterator)));
      }
      return results;
    } finally {
      this.metrics?.dbReadItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, results.length);
      cursorDeinit(iterator);
      transactionAbort(tx);
    }
  }

  async* keysStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<Uint8Array> {
    for await (const {key} of this._iterate(opts)) {
      yield key;
    }
  }

  async keys(opts: FilterOptions<Uint8Array> = {}): Promise<Uint8Array[]> {
    return this._collect(opts, (key) => key);
  }

  async* valuesStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<Uint8Array> {
    for await (const {value} of this._iterate(opts)) {
      yield value;
    }
  }

  async values(opts: FilterOptions<Uint8Array> = {}): Promise<Uint8Array[]> {
    return this._collect(opts, (_, value) => value);
  }

  entriesStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<KeyValue<Uint8Array, Uint8Array>> {
    return this._iterate(opts);
  }

  async entries(opts: FilterOptions<Uint8Array> = {}): Promise<KeyValue<Uint8Array, Uint8Array>[]> {
    return this._collect(opts, (key, value) => ({key, value}));
  }
}

Comment on lines +70 to +78
if (options.db.type === "level") {
controller = await LevelDbController.create(options.db, {metrics: null, logger});
logger.info("Connected to LevelDB database", {path: options.db.name});
} else if (options.db.type === "lmdb") {
controller = await LmdbController.create(options.db, {metrics: null, logger});
logger.info("Connected to LMDB database", {path: options.db.name});
} else {
throw new Error(`Unsupported db type: ${options.db.type}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

That logic might go well as static method inside BeaconDb as BeaconDB.init. This will help us reuse it.

metrics?: LevelDbControllerMetrics | null;
};

export class LmdbController implements DatabaseController<Uint8Array, Uint8Array> {
Copy link
Contributor

Choose a reason for hiding this comment

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

This code must be covered with unit tests. May be using same fixture to test different implementations of db controllers.

It is important as if something missed goes wrong here make it very difficult to debug on higher layers.

Copy link
Contributor

github-actions bot commented Sep 30, 2025

Performance Report

🚀🚀 Significant benchmark improvement detected

Benchmark suite Current: 72542c4 Previous: 901d719 Ratio
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 5.4570 us/op 18.075 us/op 0.30
Array.fill - length 1000000 2.4705 ms/op 9.2203 ms/op 0.27
Full benchmark results
Benchmark suite Current: 72542c4 Previous: 901d719 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 851.65 us/op 1.0244 ms/op 0.83
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 30.870 us/op 40.708 us/op 0.76
BLS verify - blst 1.0506 ms/op 1.2327 ms/op 0.85
BLS verifyMultipleSignatures 3 - blst 1.3664 ms/op 1.3003 ms/op 1.05
BLS verifyMultipleSignatures 8 - blst 2.2886 ms/op 2.0165 ms/op 1.13
BLS verifyMultipleSignatures 32 - blst 4.6519 ms/op 6.5968 ms/op 0.71
BLS verifyMultipleSignatures 64 - blst 9.3692 ms/op 11.405 ms/op 0.82
BLS verifyMultipleSignatures 128 - blst 16.033 ms/op 18.991 ms/op 0.84
BLS deserializing 10000 signatures 634.81 ms/op 695.53 ms/op 0.91
BLS deserializing 100000 signatures 6.3024 s/op 7.0980 s/op 0.89
BLS verifyMultipleSignatures - same message - 3 - blst 931.56 us/op 1.1593 ms/op 0.80
BLS verifyMultipleSignatures - same message - 8 - blst 1.0018 ms/op 1.2239 ms/op 0.82
BLS verifyMultipleSignatures - same message - 32 - blst 1.5694 ms/op 1.7143 ms/op 0.92
BLS verifyMultipleSignatures - same message - 64 - blst 2.4709 ms/op 2.6593 ms/op 0.93
BLS verifyMultipleSignatures - same message - 128 - blst 4.0884 ms/op 4.4664 ms/op 0.92
BLS aggregatePubkeys 32 - blst 17.434 us/op 20.991 us/op 0.83
BLS aggregatePubkeys 128 - blst 62.702 us/op 70.998 us/op 0.88
notSeenSlots=1 numMissedVotes=1 numBadVotes=10 44.241 ms/op 54.845 ms/op 0.81
notSeenSlots=1 numMissedVotes=0 numBadVotes=4 54.310 ms/op 55.359 ms/op 0.98
notSeenSlots=2 numMissedVotes=1 numBadVotes=10 40.283 ms/op 44.417 ms/op 0.91
getSlashingsAndExits - default max 51.274 us/op 71.758 us/op 0.71
getSlashingsAndExits - 2k 398.73 us/op 369.57 us/op 1.08
isKnown best case - 1 super set check 421.00 ns/op 216.00 ns/op 1.95
isKnown normal case - 2 super set checks 420.00 ns/op 208.00 ns/op 2.02
isKnown worse case - 16 super set checks 423.00 ns/op 210.00 ns/op 2.01
InMemoryCheckpointStateCache - add get delete 3.0010 us/op 2.3890 us/op 1.26
validate api signedAggregateAndProof - struct 1.7818 ms/op 1.6281 ms/op 1.09
validate gossip signedAggregateAndProof - struct 1.6445 ms/op 1.6751 ms/op 0.98
batch validate gossip attestation - vc 640000 - chunk 32 108.75 us/op 126.63 us/op 0.86
batch validate gossip attestation - vc 640000 - chunk 64 93.808 us/op 110.93 us/op 0.85
batch validate gossip attestation - vc 640000 - chunk 128 84.632 us/op 102.43 us/op 0.83
batch validate gossip attestation - vc 640000 - chunk 256 82.464 us/op 107.19 us/op 0.77
pickEth1Vote - no votes 742.81 us/op 1.1118 ms/op 0.67
pickEth1Vote - max votes 6.9740 ms/op 9.0324 ms/op 0.77
pickEth1Vote - Eth1Data hashTreeRoot value x2048 10.031 ms/op 16.028 ms/op 0.63
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 14.625 ms/op 20.753 ms/op 0.70
pickEth1Vote - Eth1Data fastSerialize value x2048 378.94 us/op 496.62 us/op 0.76
pickEth1Vote - Eth1Data fastSerialize tree x2048 2.4549 ms/op 2.5927 ms/op 0.95
bytes32 toHexString 525.00 ns/op 397.00 ns/op 1.32
bytes32 Buffer.toString(hex) 425.00 ns/op 256.00 ns/op 1.66
bytes32 Buffer.toString(hex) from Uint8Array 493.00 ns/op 397.00 ns/op 1.24
bytes32 Buffer.toString(hex) + 0x 426.00 ns/op 279.00 ns/op 1.53
Object access 1 prop 0.31100 ns/op 0.13100 ns/op 2.37
Map access 1 prop 0.31800 ns/op 0.13300 ns/op 2.39
Object get x1000 5.4370 ns/op 5.9930 ns/op 0.91
Map get x1000 6.1760 ns/op 6.7250 ns/op 0.92
Object set x1000 18.820 ns/op 34.032 ns/op 0.55
Map set x1000 16.504 ns/op 22.150 ns/op 0.75
Return object 10000 times 0.29150 ns/op 0.30570 ns/op 0.95
Throw Error 10000 times 3.4661 us/op 4.8026 us/op 0.72
toHex 108.97 ns/op 136.27 ns/op 0.80
Buffer.from 96.922 ns/op 129.38 ns/op 0.75
shared Buffer 68.578 ns/op 85.418 ns/op 0.80
fastMsgIdFn sha256 / 200 bytes 1.9230 us/op 2.3950 us/op 0.80
fastMsgIdFn h32 xxhash / 200 bytes 384.00 ns/op 240.00 ns/op 1.60
fastMsgIdFn h64 xxhash / 200 bytes 433.00 ns/op 294.00 ns/op 1.47
fastMsgIdFn sha256 / 1000 bytes 5.7540 us/op 7.8440 us/op 0.73
fastMsgIdFn h32 xxhash / 1000 bytes 502.00 ns/op 364.00 ns/op 1.38
fastMsgIdFn h64 xxhash / 1000 bytes 503.00 ns/op 396.00 ns/op 1.27
fastMsgIdFn sha256 / 10000 bytes 49.197 us/op 70.648 us/op 0.70
fastMsgIdFn h32 xxhash / 10000 bytes 1.8590 us/op 1.9380 us/op 0.96
fastMsgIdFn h64 xxhash / 10000 bytes 1.3160 us/op 1.2740 us/op 1.03
send data - 1000 256B messages 11.698 ms/op 22.402 ms/op 0.52
send data - 1000 512B messages 14.978 ms/op 25.022 ms/op 0.60
send data - 1000 1024B messages 20.116 ms/op 32.804 ms/op 0.61
send data - 1000 1200B messages 14.366 ms/op 28.474 ms/op 0.50
send data - 1000 2048B messages 16.204 ms/op 37.420 ms/op 0.43
send data - 1000 4096B messages 15.721 ms/op 36.852 ms/op 0.43
send data - 1000 16384B messages 24.387 ms/op 58.981 ms/op 0.41
send data - 1000 65536B messages 62.011 ms/op 146.39 ms/op 0.42
enrSubnets - fastDeserialize 64 bits 976.00 ns/op 942.00 ns/op 1.04
enrSubnets - ssz BitVector 64 bits 475.00 ns/op 345.00 ns/op 1.38
enrSubnets - fastDeserialize 4 bits 300.00 ns/op 151.00 ns/op 1.99
enrSubnets - ssz BitVector 4 bits 487.00 ns/op 365.00 ns/op 1.33
prioritizePeers score -10:0 att 32-0.1 sync 2-0 198.58 us/op 254.21 us/op 0.78
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 218.91 us/op 289.75 us/op 0.76
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 363.42 us/op 432.59 us/op 0.84
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 635.28 us/op 816.69 us/op 0.78
prioritizePeers score 0:0 att 64-1 sync 4-1 766.94 us/op 983.82 us/op 0.78
array of 16000 items push then shift 1.2739 us/op 1.7252 us/op 0.74
LinkedList of 16000 items push then shift 6.2490 ns/op 10.058 ns/op 0.62
array of 16000 items push then pop 62.134 ns/op 88.472 ns/op 0.70
LinkedList of 16000 items push then pop 6.1330 ns/op 8.9650 ns/op 0.68
array of 24000 items push then shift 1.8757 us/op 2.5171 us/op 0.75
LinkedList of 24000 items push then shift 6.2450 ns/op 11.098 ns/op 0.56
array of 24000 items push then pop 87.037 ns/op 119.81 ns/op 0.73
LinkedList of 24000 items push then pop 6.1830 ns/op 9.2190 ns/op 0.67
intersect bitArray bitLen 8 5.1080 ns/op 7.1530 ns/op 0.71
intersect array and set length 8 30.347 ns/op 42.610 ns/op 0.71
intersect bitArray bitLen 128 25.702 ns/op 32.727 ns/op 0.79
intersect array and set length 128 539.24 ns/op 664.71 ns/op 0.81
bitArray.getTrueBitIndexes() bitLen 128 1.1070 us/op 1.0210 us/op 1.08
bitArray.getTrueBitIndexes() bitLen 248 1.7500 us/op 1.8560 us/op 0.94
bitArray.getTrueBitIndexes() bitLen 512 3.2030 us/op 3.8540 us/op 0.83
Buffer.concat 32 items 775.00 ns/op 674.00 ns/op 1.15
Uint8Array.set 32 items 1.0060 us/op 1.1560 us/op 0.87
Buffer.copy 2.0580 us/op 2.1390 us/op 0.96
Uint8Array.set - with subarray 1.6960 us/op 1.6180 us/op 1.05
Uint8Array.set - without subarray 1.0990 us/op 992.00 ns/op 1.11
getUint32 - dataview 361.00 ns/op 226.00 ns/op 1.60
getUint32 - manual 289.00 ns/op 136.00 ns/op 2.13
Set add up to 64 items then delete first 1.7015 us/op 2.9735 us/op 0.57
OrderedSet add up to 64 items then delete first 2.6637 us/op 4.9017 us/op 0.54
Set add up to 64 items then delete last 1.8255 us/op 3.5284 us/op 0.52
OrderedSet add up to 64 items then delete last 2.9153 us/op 5.2262 us/op 0.56
Set add up to 64 items then delete middle 1.7449 us/op 3.5696 us/op 0.49
OrderedSet add up to 64 items then delete middle 4.3535 us/op 6.9385 us/op 0.63
Set add up to 128 items then delete first 3.9015 us/op 6.9006 us/op 0.57
OrderedSet add up to 128 items then delete first 6.0161 us/op 11.262 us/op 0.53
Set add up to 128 items then delete last 3.6476 us/op 6.8506 us/op 0.53
OrderedSet add up to 128 items then delete last 5.7072 us/op 11.200 us/op 0.51
Set add up to 128 items then delete middle 3.6613 us/op 7.0616 us/op 0.52
OrderedSet add up to 128 items then delete middle 11.180 us/op 17.367 us/op 0.64
Set add up to 256 items then delete first 7.4694 us/op 13.959 us/op 0.54
OrderedSet add up to 256 items then delete first 12.165 us/op 26.648 us/op 0.46
Set add up to 256 items then delete last 7.4317 us/op 14.979 us/op 0.50
OrderedSet add up to 256 items then delete last 11.518 us/op 20.982 us/op 0.55
Set add up to 256 items then delete middle 7.6170 us/op 14.098 us/op 0.54
OrderedSet add up to 256 items then delete middle 36.644 us/op 48.496 us/op 0.76
transfer serialized Status (84 B) 1.8230 us/op 2.5810 us/op 0.71
copy serialized Status (84 B) 1.1990 us/op 1.6670 us/op 0.72
transfer serialized SignedVoluntaryExit (112 B) 1.9440 us/op 3.2020 us/op 0.61
copy serialized SignedVoluntaryExit (112 B) 1.2130 us/op 1.7370 us/op 0.70
transfer serialized ProposerSlashing (416 B) 2.0440 us/op 2.8980 us/op 0.71
copy serialized ProposerSlashing (416 B) 1.4020 us/op 2.2770 us/op 0.62
transfer serialized Attestation (485 B) 1.8860 us/op 3.4210 us/op 0.55
copy serialized Attestation (485 B) 1.2090 us/op 2.1700 us/op 0.56
transfer serialized AttesterSlashing (33232 B) 1.9810 us/op 3.5200 us/op 0.56
copy serialized AttesterSlashing (33232 B) 3.2250 us/op 5.6490 us/op 0.57
transfer serialized Small SignedBeaconBlock (128000 B) 2.1240 us/op 3.7930 us/op 0.56
copy serialized Small SignedBeaconBlock (128000 B) 8.4980 us/op 16.804 us/op 0.51
transfer serialized Avg SignedBeaconBlock (200000 B) 2.2520 us/op 4.6270 us/op 0.49
copy serialized Avg SignedBeaconBlock (200000 B) 12.262 us/op 21.912 us/op 0.56
transfer serialized BlobsSidecar (524380 B) 2.6210 us/op 5.0660 us/op 0.52
copy serialized BlobsSidecar (524380 B) 56.862 us/op 116.27 us/op 0.49
transfer serialized Big SignedBeaconBlock (1000000 B) 3.1240 us/op 4.6700 us/op 0.67
copy serialized Big SignedBeaconBlock (1000000 B) 167.41 us/op 143.67 us/op 1.17
pass gossip attestations to forkchoice per slot 2.3347 ms/op 2.8584 ms/op 0.82
forkChoice updateHead vc 100000 bc 64 eq 0 388.36 us/op 480.61 us/op 0.81
forkChoice updateHead vc 600000 bc 64 eq 0 2.3456 ms/op 3.2657 ms/op 0.72
forkChoice updateHead vc 1000000 bc 64 eq 0 4.0673 ms/op 5.9011 ms/op 0.69
forkChoice updateHead vc 600000 bc 320 eq 0 2.0917 ms/op 3.4685 ms/op 0.60
forkChoice updateHead vc 600000 bc 1200 eq 0 2.5085 ms/op 3.4726 ms/op 0.72
forkChoice updateHead vc 600000 bc 7200 eq 0 2.5357 ms/op 3.8306 ms/op 0.66
forkChoice updateHead vc 600000 bc 64 eq 1000 9.0187 ms/op 11.233 ms/op 0.80
forkChoice updateHead vc 600000 bc 64 eq 10000 9.2514 ms/op 11.256 ms/op 0.82
forkChoice updateHead vc 600000 bc 64 eq 300000 11.134 ms/op 14.373 ms/op 0.77
computeDeltas 500000 validators 300 proto nodes 3.1182 ms/op 4.1742 ms/op 0.75
computeDeltas 500000 validators 1200 proto nodes 3.1382 ms/op 6.4063 ms/op 0.49
computeDeltas 500000 validators 7200 proto nodes 3.1459 ms/op 4.7454 ms/op 0.66
computeDeltas 750000 validators 300 proto nodes 4.8194 ms/op 7.1904 ms/op 0.67
computeDeltas 750000 validators 1200 proto nodes 4.8760 ms/op 7.7080 ms/op 0.63
computeDeltas 750000 validators 7200 proto nodes 4.9141 ms/op 7.8353 ms/op 0.63
computeDeltas 1400000 validators 300 proto nodes 9.3211 ms/op 14.159 ms/op 0.66
computeDeltas 1400000 validators 1200 proto nodes 9.3981 ms/op 13.647 ms/op 0.69
computeDeltas 1400000 validators 7200 proto nodes 9.0916 ms/op 12.322 ms/op 0.74
computeDeltas 2100000 validators 300 proto nodes 13.585 ms/op 19.031 ms/op 0.71
computeDeltas 2100000 validators 1200 proto nodes 13.465 ms/op 20.386 ms/op 0.66
computeDeltas 2100000 validators 7200 proto nodes 13.269 ms/op 18.933 ms/op 0.70
altair processAttestation - 250000 vs - 7PWei normalcase 1.7182 ms/op 3.3811 ms/op 0.51
altair processAttestation - 250000 vs - 7PWei worstcase 2.3487 ms/op 3.9753 ms/op 0.59
altair processAttestation - setStatus - 1/6 committees join 96.922 us/op 153.64 us/op 0.63
altair processAttestation - setStatus - 1/3 committees join 177.58 us/op 311.15 us/op 0.57
altair processAttestation - setStatus - 1/2 committees join 264.20 us/op 422.41 us/op 0.63
altair processAttestation - setStatus - 2/3 committees join 343.77 us/op 545.96 us/op 0.63
altair processAttestation - setStatus - 4/5 committees join 477.92 us/op 679.88 us/op 0.70
altair processAttestation - setStatus - 100% committees join 573.24 us/op 792.86 us/op 0.72
altair processBlock - 250000 vs - 7PWei normalcase 4.5715 ms/op 9.2422 ms/op 0.49
altair processBlock - 250000 vs - 7PWei normalcase hashState 27.477 ms/op 44.484 ms/op 0.62
altair processBlock - 250000 vs - 7PWei worstcase 37.413 ms/op 48.002 ms/op 0.78
altair processBlock - 250000 vs - 7PWei worstcase hashState 80.848 ms/op 110.71 ms/op 0.73
phase0 processBlock - 250000 vs - 7PWei normalcase 1.4252 ms/op 2.7272 ms/op 0.52
phase0 processBlock - 250000 vs - 7PWei worstcase 26.822 ms/op 36.096 ms/op 0.74
altair processEth1Data - 250000 vs - 7PWei normalcase 280.43 us/op 590.88 us/op 0.47
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 5.4550 us/op 13.356 us/op 0.41
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 34.218 us/op 62.088 us/op 0.55
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 5.4570 us/op 18.075 us/op 0.30
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 5.8690 us/op 11.248 us/op 0.52
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 91.480 us/op 211.53 us/op 0.43
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.4983 ms/op 2.6340 ms/op 0.57
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.7563 ms/op 2.9631 ms/op 0.59
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.7544 ms/op 4.1950 ms/op 0.42
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.5475 ms/op 9.8564 ms/op 0.36
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 1.7772 ms/op 3.3784 ms/op 0.53
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 3.6093 ms/op 7.5217 ms/op 0.48
Tree 40 250000 create 364.23 ms/op 776.21 ms/op 0.47
Tree 40 250000 get(125000) 109.85 ns/op 154.12 ns/op 0.71
Tree 40 250000 set(125000) 1.3047 us/op 2.5513 us/op 0.51
Tree 40 250000 toArray() 17.449 ms/op 27.964 ms/op 0.62
Tree 40 250000 iterate all - toArray() + loop 16.896 ms/op 36.275 ms/op 0.47
Tree 40 250000 iterate all - get(i) 43.942 ms/op 68.348 ms/op 0.64
Array 250000 create 2.6352 ms/op 5.0599 ms/op 0.52
Array 250000 clone - spread 665.15 us/op 3.1848 ms/op 0.21
Array 250000 get(125000) 0.56800 ns/op 0.45600 ns/op 1.25
Array 250000 set(125000) 0.58200 ns/op 0.51000 ns/op 1.14
Array 250000 iterate all - loop 75.360 us/op 89.835 us/op 0.84
phase0 afterProcessEpoch - 250000 vs - 7PWei 37.718 ms/op 45.734 ms/op 0.82
Array.fill - length 1000000 2.4705 ms/op 9.2203 ms/op 0.27
Array push - length 1000000 16.152 ms/op 29.034 ms/op 0.56
Array.get 0.26052 ns/op 0.30618 ns/op 0.85
Uint8Array.get 0.33948 ns/op 0.57734 ns/op 0.59
phase0 beforeProcessEpoch - 250000 vs - 7PWei 17.348 ms/op 31.022 ms/op 0.56
altair processEpoch - mainnet_e81889 306.23 ms/op 400.92 ms/op 0.76
mainnet_e81889 - altair beforeProcessEpoch 16.664 ms/op 24.513 ms/op 0.68
mainnet_e81889 - altair processJustificationAndFinalization 5.7770 us/op 8.0320 us/op 0.72
mainnet_e81889 - altair processInactivityUpdates 5.6289 ms/op 7.1110 ms/op 0.79
mainnet_e81889 - altair processRewardsAndPenalties 40.194 ms/op 47.664 ms/op 0.84
mainnet_e81889 - altair processRegistryUpdates 872.00 ns/op 822.00 ns/op 1.06
mainnet_e81889 - altair processSlashings 398.00 ns/op 206.00 ns/op 1.93
mainnet_e81889 - altair processEth1DataReset 395.00 ns/op 197.00 ns/op 2.01
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.5324 ms/op 1.2444 ms/op 1.23
mainnet_e81889 - altair processSlashingsReset 1.0210 us/op 1.0390 us/op 0.98
mainnet_e81889 - altair processRandaoMixesReset 1.2420 us/op 1.4650 us/op 0.85
mainnet_e81889 - altair processHistoricalRootsUpdate 394.00 ns/op 193.00 ns/op 2.04
mainnet_e81889 - altair processParticipationFlagUpdates 717.00 ns/op 620.00 ns/op 1.16
mainnet_e81889 - altair processSyncCommitteeUpdates 372.00 ns/op 152.00 ns/op 2.45
mainnet_e81889 - altair afterProcessEpoch 40.061 ms/op 46.819 ms/op 0.86
capella processEpoch - mainnet_e217614 787.00 ms/op 1.0358 s/op 0.76
mainnet_e217614 - capella beforeProcessEpoch 58.321 ms/op 62.578 ms/op 0.93
mainnet_e217614 - capella processJustificationAndFinalization 4.5360 us/op 5.3770 us/op 0.84
mainnet_e217614 - capella processInactivityUpdates 12.213 ms/op 14.790 ms/op 0.83
mainnet_e217614 - capella processRewardsAndPenalties 187.19 ms/op 181.15 ms/op 1.03
mainnet_e217614 - capella processRegistryUpdates 5.3280 us/op 6.8450 us/op 0.78
mainnet_e217614 - capella processSlashings 395.00 ns/op 195.00 ns/op 2.03
mainnet_e217614 - capella processEth1DataReset 395.00 ns/op 187.00 ns/op 2.11
mainnet_e217614 - capella processEffectiveBalanceUpdates 14.758 ms/op 4.1908 ms/op 3.52
mainnet_e217614 - capella processSlashingsReset 1.0190 us/op 927.00 ns/op 1.10
mainnet_e217614 - capella processRandaoMixesReset 1.2610 us/op 1.3330 us/op 0.95
mainnet_e217614 - capella processHistoricalRootsUpdate 406.00 ns/op 200.00 ns/op 2.03
mainnet_e217614 - capella processParticipationFlagUpdates 741.00 ns/op 546.00 ns/op 1.36
mainnet_e217614 - capella afterProcessEpoch 108.29 ms/op 116.89 ms/op 0.93
phase0 processEpoch - mainnet_e58758 293.33 ms/op 299.21 ms/op 0.98
mainnet_e58758 - phase0 beforeProcessEpoch 80.905 ms/op 78.723 ms/op 1.03
mainnet_e58758 - phase0 processJustificationAndFinalization 4.7750 us/op 6.0120 us/op 0.79
mainnet_e58758 - phase0 processRewardsAndPenalties 33.062 ms/op 41.108 ms/op 0.80
mainnet_e58758 - phase0 processRegistryUpdates 2.7910 us/op 3.3320 us/op 0.84
mainnet_e58758 - phase0 processSlashings 457.00 ns/op 180.00 ns/op 2.54
mainnet_e58758 - phase0 processEth1DataReset 397.00 ns/op 195.00 ns/op 2.04
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 950.81 us/op 1.1878 ms/op 0.80
mainnet_e58758 - phase0 processSlashingsReset 1.3580 us/op 958.00 ns/op 1.42
mainnet_e58758 - phase0 processRandaoMixesReset 1.2760 us/op 1.1490 us/op 1.11
mainnet_e58758 - phase0 processHistoricalRootsUpdate 401.00 ns/op 238.00 ns/op 1.68
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.2160 us/op 925.00 ns/op 1.31
mainnet_e58758 - phase0 afterProcessEpoch 32.495 ms/op 35.858 ms/op 0.91
phase0 processEffectiveBalanceUpdates - 250000 normalcase 984.98 us/op 1.3760 ms/op 0.72
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 2.0650 ms/op 2.2854 ms/op 0.90
altair processInactivityUpdates - 250000 normalcase 18.088 ms/op 21.103 ms/op 0.86
altair processInactivityUpdates - 250000 worstcase 18.473 ms/op 20.547 ms/op 0.90
phase0 processRegistryUpdates - 250000 normalcase 5.7020 us/op 9.3160 us/op 0.61
phase0 processRegistryUpdates - 250000 badcase_full_deposits 290.75 us/op 324.32 us/op 0.90
phase0 processRegistryUpdates - 250000 worstcase 0.5 102.91 ms/op 108.95 ms/op 0.94
altair processRewardsAndPenalties - 250000 normalcase 22.787 ms/op 26.556 ms/op 0.86
altair processRewardsAndPenalties - 250000 worstcase 21.796 ms/op 29.226 ms/op 0.75
phase0 getAttestationDeltas - 250000 normalcase 4.8486 ms/op 7.6631 ms/op 0.63
phase0 getAttestationDeltas - 250000 worstcase 5.3621 ms/op 6.2972 ms/op 0.85
phase0 processSlashings - 250000 worstcase 95.847 us/op 129.06 us/op 0.74
altair processSyncCommitteeUpdates - 250000 9.8112 ms/op 10.933 ms/op 0.90
BeaconState.hashTreeRoot - No change 473.00 ns/op 216.00 ns/op 2.19
BeaconState.hashTreeRoot - 1 full validator 70.406 us/op 73.553 us/op 0.96
BeaconState.hashTreeRoot - 32 full validator 659.82 us/op 751.03 us/op 0.88
BeaconState.hashTreeRoot - 512 full validator 7.2602 ms/op 9.9266 ms/op 0.73
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 74.426 us/op 89.584 us/op 0.83
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.3890 ms/op 1.2549 ms/op 1.11
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 24.180 ms/op 22.203 ms/op 1.09
BeaconState.hashTreeRoot - 1 balances 69.971 us/op 85.506 us/op 0.82
BeaconState.hashTreeRoot - 32 balances 728.94 us/op 660.22 us/op 1.10
BeaconState.hashTreeRoot - 512 balances 6.6270 ms/op 6.9231 ms/op 0.96
BeaconState.hashTreeRoot - 250000 balances 116.96 ms/op 183.19 ms/op 0.64
aggregationBits - 2048 els - zipIndexesInBitList 18.257 us/op 23.584 us/op 0.77
byteArrayEquals 32 47.576 ns/op 56.602 ns/op 0.84
Buffer.compare 32 16.242 ns/op 18.481 ns/op 0.88
byteArrayEquals 1024 1.2553 us/op 1.6704 us/op 0.75
Buffer.compare 1024 25.436 ns/op 27.750 ns/op 0.92
byteArrayEquals 16384 19.932 us/op 26.553 us/op 0.75
Buffer.compare 16384 170.22 ns/op 213.53 ns/op 0.80
byteArrayEquals 123687377 149.48 ms/op 192.54 ms/op 0.78
Buffer.compare 123687377 6.4440 ms/op 6.4529 ms/op 1.00
byteArrayEquals 32 - diff last byte 47.109 ns/op 53.108 ns/op 0.89
Buffer.compare 32 - diff last byte 15.624 ns/op 17.124 ns/op 0.91
byteArrayEquals 1024 - diff last byte 1.2592 us/op 1.6056 us/op 0.78
Buffer.compare 1024 - diff last byte 22.581 ns/op 25.404 ns/op 0.89
byteArrayEquals 16384 - diff last byte 19.944 us/op 25.470 us/op 0.78
Buffer.compare 16384 - diff last byte 196.19 ns/op 203.74 ns/op 0.96
byteArrayEquals 123687377 - diff last byte 153.30 ms/op 191.71 ms/op 0.80
Buffer.compare 123687377 - diff last byte 6.3239 ms/op 6.7390 ms/op 0.94
byteArrayEquals 32 - random bytes 5.0180 ns/op 5.1170 ns/op 0.98
Buffer.compare 32 - random bytes 15.799 ns/op 17.178 ns/op 0.92
byteArrayEquals 1024 - random bytes 4.9150 ns/op 5.1170 ns/op 0.96
Buffer.compare 1024 - random bytes 15.615 ns/op 17.130 ns/op 0.91
byteArrayEquals 16384 - random bytes 5.0140 ns/op 5.1170 ns/op 0.98
Buffer.compare 16384 - random bytes 15.150 ns/op 17.074 ns/op 0.89
byteArrayEquals 123687377 - random bytes 7.8300 ns/op 6.8300 ns/op 1.15
Buffer.compare 123687377 - random bytes 18.290 ns/op 19.390 ns/op 0.94
regular array get 100000 times 30.497 us/op 33.136 us/op 0.92
wrappedArray get 100000 times 30.135 us/op 33.138 us/op 0.91
arrayWithProxy get 100000 times 10.577 ms/op 12.362 ms/op 0.86
ssz.Root.equals 43.912 ns/op 46.131 ns/op 0.95
byteArrayEquals 42.635 ns/op 45.252 ns/op 0.94
Buffer.compare 8.8970 ns/op 10.299 ns/op 0.86
processSlot - 1 slots 8.8920 us/op 10.032 us/op 0.89
processSlot - 32 slots 2.3027 ms/op 2.0386 ms/op 1.13
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 3.7445 ms/op 2.9441 ms/op 1.27
getCommitteeAssignments - req 1 vs - 250000 vc 1.7819 ms/op 2.1413 ms/op 0.83
getCommitteeAssignments - req 100 vs - 250000 vc 3.5958 ms/op 4.1161 ms/op 0.87
getCommitteeAssignments - req 1000 vs - 250000 vc 3.8488 ms/op 4.3826 ms/op 0.88
findModifiedValidators - 10000 modified validators 746.86 ms/op 723.97 ms/op 1.03
findModifiedValidators - 1000 modified validators 687.76 ms/op 664.38 ms/op 1.04
findModifiedValidators - 100 modified validators 219.99 ms/op 269.92 ms/op 0.82
findModifiedValidators - 10 modified validators 150.00 ms/op 250.73 ms/op 0.60
findModifiedValidators - 1 modified validators 136.36 ms/op 171.25 ms/op 0.80
findModifiedValidators - no difference 139.91 ms/op 149.73 ms/op 0.93
compare ViewDUs 6.6392 s/op 6.4090 s/op 1.04
compare each validator Uint8Array 1.4653 s/op 1.5167 s/op 0.97
compare ViewDU to Uint8Array 1.1621 s/op 1.2166 s/op 0.96
migrate state 1000000 validators, 24 modified, 0 new 947.91 ms/op 949.48 ms/op 1.00
migrate state 1000000 validators, 1700 modified, 1000 new 1.2873 s/op 1.2650 s/op 1.02
migrate state 1000000 validators, 3400 modified, 2000 new 1.3677 s/op 1.4661 s/op 0.93
migrate state 1500000 validators, 24 modified, 0 new 861.78 ms/op 1.1141 s/op 0.77
migrate state 1500000 validators, 1700 modified, 1000 new 1.0779 s/op 1.2990 s/op 0.83
migrate state 1500000 validators, 3400 modified, 2000 new 1.2832 s/op 1.3320 s/op 0.96
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 6.0400 ns/op 4.0600 ns/op 1.49
state getBlockRootAtSlot - 250000 vs - 7PWei 574.49 ns/op 1.0036 us/op 0.57
naive computeProposerIndex 100000 validators 42.250 ms/op 48.644 ms/op 0.87
computeProposerIndex 100000 validators 1.2983 ms/op 1.4600 ms/op 0.89
naiveGetNextSyncCommitteeIndices 1000 validators 6.1488 s/op 7.6028 s/op 0.81
getNextSyncCommitteeIndices 1000 validators 94.693 ms/op 121.47 ms/op 0.78
naiveGetNextSyncCommitteeIndices 10000 validators 5.9106 s/op 8.0809 s/op 0.73
getNextSyncCommitteeIndices 10000 validators 91.612 ms/op 124.19 ms/op 0.74
naiveGetNextSyncCommitteeIndices 100000 validators 6.0401 s/op 7.4955 s/op 0.81
getNextSyncCommitteeIndices 100000 validators 94.041 ms/op 117.64 ms/op 0.80
naive computeShuffledIndex 100000 validators 18.920 s/op 25.380 s/op 0.75
cached computeShuffledIndex 100000 validators 459.99 ms/op 575.45 ms/op 0.80
naive computeShuffledIndex 2000000 validators 401.27 s/op 509.39 s/op 0.79
cached computeShuffledIndex 2000000 validators 17.535 s/op 42.538 s/op 0.41
computeProposers - vc 250000 517.40 us/op 619.29 us/op 0.84
computeEpochShuffling - vc 250000 37.645 ms/op 41.686 ms/op 0.90
getNextSyncCommittee - vc 250000 9.2555 ms/op 10.415 ms/op 0.89
computeSigningRoot for AttestationData 17.808 us/op 19.512 us/op 0.91
hash AttestationData serialized data then Buffer.toString(base64) 1.1705 us/op 1.5737 us/op 0.74
toHexString serialized data 958.55 ns/op 1.1092 us/op 0.86
Buffer.toString(base64) 105.32 ns/op 156.42 ns/op 0.67
nodejs block root to RootHex using toHex 101.99 ns/op 144.66 ns/op 0.71
nodejs block root to RootHex using toRootHex 70.045 ns/op 87.054 ns/op 0.80
nodejs fromhex(blob) 88.096 ms/op 107.59 ms/op 0.82
nodejs fromHexInto(blob) 82.746 ms/op 91.511 ms/op 0.90
browser block root to RootHex using the deprecated toHexString 193.53 ns/op 206.64 ns/op 0.94
browser block root to RootHex using toHex 160.54 ns/op 169.10 ns/op 0.95
browser block root to RootHex using toRootHex 149.13 ns/op 155.54 ns/op 0.96
browser fromHexInto(blob) 671.76 us/op 798.67 us/op 0.84
browser fromHex(blob) 656.06 ms/op 763.15 ms/op 0.86

by benchmarkbot/action

Copy link

codecov bot commented Sep 30, 2025

Codecov Report

❌ Patch coverage is 15.78947% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.24%. Comparing base (248b252) to head (31453a3).
⚠️ Report is 1 commits behind head on unstable.

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #8483      +/-   ##
============================================
- Coverage     52.25%   52.24%   -0.02%     
============================================
  Files           852      852              
  Lines         64977    64992      +15     
  Branches       4768     4769       +1     
============================================
- Hits          33956    33955       -1     
- Misses        30952    30968      +16     
  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 Author

  • Moving to draft as this currently doesn't work
  • Also needs tests

@wemeetagain wemeetagain marked this pull request as draft October 1, 2025 20:22
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