Skip to content

Conversation

@wemeetagain
Copy link
Member

@wemeetagain wemeetagain commented Sep 30, 2025

Motivation

Description

  • Add LmdbController -- uses the lmdb binding from lodestar-bun in bun, empty implementation in nodejs
  • Add SqliteController -- uses the buildin bun:sqlite or node:sqlite depending on the runtime
  • Add --dbType hidden flag to select "level" | "lmdb" | "sqlite"

@wemeetagain wemeetagain requested a review from a team as a code owner September 30, 2025 15:00
@gemini-code-assist
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.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 30, 2025

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 005d24f Previous: 9dbc67b Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 910.60 us/op 987.42 us/op 0.92
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 33.896 us/op 35.421 us/op 0.96
BLS verify - blst 825.96 us/op 837.96 us/op 0.99
BLS verifyMultipleSignatures 3 - blst 1.2453 ms/op 1.2296 ms/op 1.01
BLS verifyMultipleSignatures 8 - blst 2.0901 ms/op 1.6664 ms/op 1.25
BLS verifyMultipleSignatures 32 - blst 6.6554 ms/op 4.8777 ms/op 1.36
BLS verifyMultipleSignatures 64 - blst 10.293 ms/op 9.0370 ms/op 1.14
BLS verifyMultipleSignatures 128 - blst 17.004 ms/op 17.316 ms/op 0.98
BLS deserializing 10000 signatures 656.39 ms/op 697.85 ms/op 0.94
BLS deserializing 100000 signatures 6.6057 s/op 7.1269 s/op 0.93
BLS verifyMultipleSignatures - same message - 3 - blst 822.56 us/op 922.36 us/op 0.89
BLS verifyMultipleSignatures - same message - 8 - blst 954.81 us/op 996.93 us/op 0.96
BLS verifyMultipleSignatures - same message - 32 - blst 1.7630 ms/op 1.6554 ms/op 1.06
BLS verifyMultipleSignatures - same message - 64 - blst 2.8107 ms/op 2.6678 ms/op 1.05
BLS verifyMultipleSignatures - same message - 128 - blst 4.5496 ms/op 4.3739 ms/op 1.04
BLS aggregatePubkeys 32 - blst 18.610 us/op 19.418 us/op 0.96
BLS aggregatePubkeys 128 - blst 66.290 us/op 69.622 us/op 0.95
notSeenSlots=1 numMissedVotes=1 numBadVotes=10 71.429 ms/op 48.143 ms/op 1.48
notSeenSlots=1 numMissedVotes=0 numBadVotes=4 49.523 ms/op 52.709 ms/op 0.94
notSeenSlots=2 numMissedVotes=1 numBadVotes=10 43.928 ms/op 38.578 ms/op 1.14
getSlashingsAndExits - default max 71.654 us/op 73.460 us/op 0.98
getSlashingsAndExits - 2k 312.58 us/op 384.86 us/op 0.81
isKnown best case - 1 super set check 201.00 ns/op 217.00 ns/op 0.93
isKnown normal case - 2 super set checks 197.00 ns/op 218.00 ns/op 0.90
isKnown worse case - 16 super set checks 200.00 ns/op 217.00 ns/op 0.92
InMemoryCheckpointStateCache - add get delete 2.2970 us/op 2.5330 us/op 0.91
validate api signedAggregateAndProof - struct 2.1057 ms/op 1.4202 ms/op 1.48
validate gossip signedAggregateAndProof - struct 1.3814 ms/op 1.4547 ms/op 0.95
batch validate gossip attestation - vc 640000 - chunk 32 116.17 us/op 122.47 us/op 0.95
batch validate gossip attestation - vc 640000 - chunk 64 101.56 us/op 108.93 us/op 0.93
batch validate gossip attestation - vc 640000 - chunk 128 93.675 us/op 104.09 us/op 0.90
batch validate gossip attestation - vc 640000 - chunk 256 93.215 us/op 112.04 us/op 0.83
pickEth1Vote - no votes 948.23 us/op 1.0485 ms/op 0.90
pickEth1Vote - max votes 6.7303 ms/op 8.1988 ms/op 0.82
pickEth1Vote - Eth1Data hashTreeRoot value x2048 12.442 ms/op 14.362 ms/op 0.87
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 18.793 ms/op 26.708 ms/op 0.70
pickEth1Vote - Eth1Data fastSerialize value x2048 432.10 us/op 454.03 us/op 0.95
pickEth1Vote - Eth1Data fastSerialize tree x2048 2.3165 ms/op 3.1853 ms/op 0.73
bytes32 toHexString 352.00 ns/op 403.00 ns/op 0.87
bytes32 Buffer.toString(hex) 232.00 ns/op 254.00 ns/op 0.91
bytes32 Buffer.toString(hex) from Uint8Array 325.00 ns/op 366.00 ns/op 0.89
bytes32 Buffer.toString(hex) + 0x 232.00 ns/op 257.00 ns/op 0.90
Object access 1 prop 0.11200 ns/op 0.12800 ns/op 0.88
Map access 1 prop 0.11500 ns/op 0.13400 ns/op 0.86
Object get x1000 5.7030 ns/op 6.2750 ns/op 0.91
Map get x1000 6.2560 ns/op 6.7990 ns/op 0.92
Object set x1000 27.420 ns/op 36.670 ns/op 0.75
Map set x1000 18.883 ns/op 24.267 ns/op 0.78
Return object 10000 times 0.27820 ns/op 0.31450 ns/op 0.88
Throw Error 10000 times 4.0551 us/op 4.9431 us/op 0.82
toHex 128.31 ns/op 147.46 ns/op 0.87
Buffer.from 121.65 ns/op 134.76 ns/op 0.90
shared Buffer 75.892 ns/op 84.607 ns/op 0.90
fastMsgIdFn sha256 / 200 bytes 2.1120 us/op 2.4180 us/op 0.87
fastMsgIdFn h32 xxhash / 200 bytes 193.00 ns/op 218.00 ns/op 0.89
fastMsgIdFn h64 xxhash / 200 bytes 241.00 ns/op 274.00 ns/op 0.88
fastMsgIdFn sha256 / 1000 bytes 7.1000 us/op 7.8180 us/op 0.91
fastMsgIdFn h32 xxhash / 1000 bytes 323.00 ns/op 359.00 ns/op 0.90
fastMsgIdFn h64 xxhash / 1000 bytes 313.00 ns/op 358.00 ns/op 0.87
fastMsgIdFn sha256 / 10000 bytes 65.472 us/op 69.569 us/op 0.94
fastMsgIdFn h32 xxhash / 10000 bytes 1.7860 us/op 2.2260 us/op 0.80
fastMsgIdFn h64 xxhash / 10000 bytes 1.1760 us/op 1.3360 us/op 0.88
send data - 1000 256B messages 14.967 ms/op 24.009 ms/op 0.62
send data - 1000 512B messages 18.081 ms/op 27.388 ms/op 0.66
send data - 1000 1024B messages 25.529 ms/op 34.461 ms/op 0.74
send data - 1000 1200B messages 22.183 ms/op 49.484 ms/op 0.45
send data - 1000 2048B messages 22.752 ms/op 33.831 ms/op 0.67
send data - 1000 4096B messages 25.667 ms/op 39.438 ms/op 0.65
send data - 1000 16384B messages 41.866 ms/op 58.451 ms/op 0.72
send data - 1000 65536B messages 108.99 ms/op 153.96 ms/op 0.71
enrSubnets - fastDeserialize 64 bits 852.00 ns/op 960.00 ns/op 0.89
enrSubnets - ssz BitVector 64 bits 314.00 ns/op 351.00 ns/op 0.89
enrSubnets - fastDeserialize 4 bits 121.00 ns/op 132.00 ns/op 0.92
enrSubnets - ssz BitVector 4 bits 315.00 ns/op 357.00 ns/op 0.88
prioritizePeers score -10:0 att 32-0.1 sync 2-0 229.63 us/op 280.81 us/op 0.82
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 252.99 us/op 327.29 us/op 0.77
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 368.41 us/op 470.25 us/op 0.78
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 690.03 us/op 849.01 us/op 0.81
prioritizePeers score 0:0 att 64-1 sync 4-1 820.48 us/op 1.0254 ms/op 0.80
array of 16000 items push then shift 1.5692 us/op 1.7443 us/op 0.90
LinkedList of 16000 items push then shift 7.1370 ns/op 11.134 ns/op 0.64
array of 16000 items push then pop 73.667 ns/op 95.165 ns/op 0.77
LinkedList of 16000 items push then pop 6.9510 ns/op 10.117 ns/op 0.69
array of 24000 items push then shift 2.3404 us/op 2.6392 us/op 0.89
LinkedList of 24000 items push then shift 7.1160 ns/op 10.034 ns/op 0.71
array of 24000 items push then pop 104.81 ns/op 132.52 ns/op 0.79
LinkedList of 24000 items push then pop 6.9830 ns/op 8.7840 ns/op 0.79
intersect bitArray bitLen 8 6.1660 ns/op 7.1180 ns/op 0.87
intersect array and set length 8 36.736 ns/op 43.600 ns/op 0.84
intersect bitArray bitLen 128 28.835 ns/op 32.534 ns/op 0.89
intersect array and set length 128 605.48 ns/op 708.20 ns/op 0.85
bitArray.getTrueBitIndexes() bitLen 128 983.00 ns/op 1.2200 us/op 0.81
bitArray.getTrueBitIndexes() bitLen 248 1.7260 us/op 2.1280 us/op 0.81
bitArray.getTrueBitIndexes() bitLen 512 3.5540 us/op 4.3310 us/op 0.82
Buffer.concat 32 items 676.00 ns/op 738.00 ns/op 0.92
Uint8Array.set 32 items 1.2780 us/op 1.6990 us/op 0.75
Buffer.copy 1.9430 us/op 2.8870 us/op 0.67
Uint8Array.set - with subarray 1.5370 us/op 2.7980 us/op 0.55
Uint8Array.set - without subarray 1.0480 us/op 1.6050 us/op 0.65
getUint32 - dataview 195.00 ns/op 214.00 ns/op 0.91
getUint32 - manual 114.00 ns/op 126.00 ns/op 0.90
Set add up to 64 items then delete first 2.1321 us/op 3.3356 us/op 0.64
OrderedSet add up to 64 items then delete first 3.2022 us/op 5.1986 us/op 0.62
Set add up to 64 items then delete last 2.2579 us/op 3.9254 us/op 0.58
OrderedSet add up to 64 items then delete last 3.7076 us/op 5.6775 us/op 0.65
Set add up to 64 items then delete middle 2.4993 us/op 3.7460 us/op 0.67
OrderedSet add up to 64 items then delete middle 5.1045 us/op 7.5660 us/op 0.67
Set add up to 128 items then delete first 4.9208 us/op 7.2351 us/op 0.68
OrderedSet add up to 128 items then delete first 7.8194 us/op 11.955 us/op 0.65
Set add up to 128 items then delete last 4.9834 us/op 7.0784 us/op 0.70
OrderedSet add up to 128 items then delete last 7.1091 us/op 12.634 us/op 0.56
Set add up to 128 items then delete middle 4.6635 us/op 7.0765 us/op 0.66
OrderedSet add up to 128 items then delete middle 13.263 us/op 18.283 us/op 0.73
Set add up to 256 items then delete first 9.6984 us/op 14.117 us/op 0.69
OrderedSet add up to 256 items then delete first 15.129 us/op 24.390 us/op 0.62
Set add up to 256 items then delete last 9.2535 us/op 15.059 us/op 0.61
OrderedSet add up to 256 items then delete last 15.129 us/op 22.838 us/op 0.66
Set add up to 256 items then delete middle 9.3168 us/op 14.252 us/op 0.65
OrderedSet add up to 256 items then delete middle 39.791 us/op 51.126 us/op 0.78
transfer serialized Status (84 B) 2.1720 us/op 3.0240 us/op 0.72
copy serialized Status (84 B) 1.1670 us/op 1.4570 us/op 0.80
transfer serialized SignedVoluntaryExit (112 B) 2.1720 us/op 2.6010 us/op 0.84
copy serialized SignedVoluntaryExit (112 B) 1.1800 us/op 1.5090 us/op 0.78
transfer serialized ProposerSlashing (416 B) 2.2510 us/op 2.8950 us/op 0.78
copy serialized ProposerSlashing (416 B) 1.6120 us/op 2.3210 us/op 0.69
transfer serialized Attestation (485 B) 2.6230 us/op 2.7860 us/op 0.94
copy serialized Attestation (485 B) 1.7270 us/op 2.5160 us/op 0.69
transfer serialized AttesterSlashing (33232 B) 2.4330 us/op 3.0090 us/op 0.81
copy serialized AttesterSlashing (33232 B) 3.4080 us/op 5.9940 us/op 0.57
transfer serialized Small SignedBeaconBlock (128000 B) 3.1570 us/op 3.4400 us/op 0.92
copy serialized Small SignedBeaconBlock (128000 B) 8.9110 us/op 17.561 us/op 0.51
transfer serialized Avg SignedBeaconBlock (200000 B) 3.6190 us/op 4.3010 us/op 0.84
copy serialized Avg SignedBeaconBlock (200000 B) 12.884 us/op 26.892 us/op 0.48
transfer serialized BlobsSidecar (524380 B) 3.0590 us/op 4.5300 us/op 0.68
copy serialized BlobsSidecar (524380 B) 97.248 us/op 108.22 us/op 0.90
transfer serialized Big SignedBeaconBlock (1000000 B) 3.1900 us/op 4.9360 us/op 0.65
copy serialized Big SignedBeaconBlock (1000000 B) 108.81 us/op 169.00 us/op 0.64
pass gossip attestations to forkchoice per slot 2.6263 ms/op 2.9276 ms/op 0.90
forkChoice updateHead vc 100000 bc 64 eq 0 457.47 us/op 555.10 us/op 0.82
forkChoice updateHead vc 600000 bc 64 eq 0 2.7440 ms/op 3.2730 ms/op 0.84
forkChoice updateHead vc 1000000 bc 64 eq 0 4.5512 ms/op 4.9659 ms/op 0.92
forkChoice updateHead vc 600000 bc 320 eq 0 2.7436 ms/op 3.0140 ms/op 0.91
forkChoice updateHead vc 600000 bc 1200 eq 0 2.7823 ms/op 3.3137 ms/op 0.84
forkChoice updateHead vc 600000 bc 7200 eq 0 2.9926 ms/op 3.3764 ms/op 0.89
forkChoice updateHead vc 600000 bc 64 eq 1000 2.7435 ms/op 3.0763 ms/op 0.89
forkChoice updateHead vc 600000 bc 64 eq 10000 2.8557 ms/op 3.2439 ms/op 0.88
forkChoice updateHead vc 600000 bc 64 eq 300000 9.1807 ms/op 10.923 ms/op 0.84
computeDeltas 1400000 validators 0% inactive 13.181 ms/op 15.089 ms/op 0.87
computeDeltas 1400000 validators 10% inactive 12.239 ms/op 13.749 ms/op 0.89
computeDeltas 1400000 validators 20% inactive 11.084 ms/op 12.368 ms/op 0.90
computeDeltas 1400000 validators 50% inactive 8.3887 ms/op 9.1499 ms/op 0.92
computeDeltas 2100000 validators 0% inactive 19.811 ms/op 22.763 ms/op 0.87
computeDeltas 2100000 validators 10% inactive 18.535 ms/op 21.097 ms/op 0.88
computeDeltas 2100000 validators 20% inactive 16.891 ms/op 18.254 ms/op 0.93
computeDeltas 2100000 validators 50% inactive 12.685 ms/op 14.102 ms/op 0.90
altair processAttestation - 250000 vs - 7PWei normalcase 1.9325 ms/op 3.9490 ms/op 0.49
altair processAttestation - 250000 vs - 7PWei worstcase 2.7678 ms/op 4.9152 ms/op 0.56
altair processAttestation - setStatus - 1/6 committees join 118.62 us/op 161.89 us/op 0.73
altair processAttestation - setStatus - 1/3 committees join 228.07 us/op 288.02 us/op 0.79
altair processAttestation - setStatus - 1/2 committees join 313.49 us/op 380.42 us/op 0.82
altair processAttestation - setStatus - 2/3 committees join 416.07 us/op 503.45 us/op 0.83
altair processAttestation - setStatus - 4/5 committees join 568.43 us/op 735.89 us/op 0.77
altair processAttestation - setStatus - 100% committees join 669.05 us/op 879.80 us/op 0.76
altair processBlock - 250000 vs - 7PWei normalcase 5.2959 ms/op 6.5509 ms/op 0.81
altair processBlock - 250000 vs - 7PWei normalcase hashState 34.234 ms/op 37.648 ms/op 0.91
altair processBlock - 250000 vs - 7PWei worstcase 48.048 ms/op 46.277 ms/op 1.04
altair processBlock - 250000 vs - 7PWei worstcase hashState 105.04 ms/op 97.332 ms/op 1.08
phase0 processBlock - 250000 vs - 7PWei normalcase 2.7844 ms/op 2.3458 ms/op 1.19
phase0 processBlock - 250000 vs - 7PWei worstcase 27.779 ms/op 29.212 ms/op 0.95
altair processEth1Data - 250000 vs - 7PWei normalcase 340.71 us/op 399.56 us/op 0.85
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 9.1530 us/op 10.926 us/op 0.84
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 56.088 us/op 62.275 us/op 0.90
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 15.820 us/op 16.762 us/op 0.94
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 9.9480 us/op 8.9420 us/op 1.11
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 249.16 us/op 217.76 us/op 1.14
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.8045 ms/op 2.0295 ms/op 0.89
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.2888 ms/op 2.6728 ms/op 0.86
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.2019 ms/op 2.7626 ms/op 0.80
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 4.4818 ms/op 6.3679 ms/op 0.70
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.3684 ms/op 2.8907 ms/op 0.82
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.6565 ms/op 5.3989 ms/op 0.86
Tree 40 250000 create 405.84 ms/op 517.29 ms/op 0.78
Tree 40 250000 get(125000) 135.66 ns/op 149.39 ns/op 0.91
Tree 40 250000 set(125000) 1.4200 us/op 1.9713 us/op 0.72
Tree 40 250000 toArray() 14.939 ms/op 21.040 ms/op 0.71
Tree 40 250000 iterate all - toArray() + loop 15.405 ms/op 22.577 ms/op 0.68
Tree 40 250000 iterate all - get(i) 48.792 ms/op 60.529 ms/op 0.81
Array 250000 create 2.8621 ms/op 3.7968 ms/op 0.75
Array 250000 clone - spread 793.27 us/op 1.5613 ms/op 0.51
Array 250000 get(125000) 0.39700 ns/op 0.43100 ns/op 0.92
Array 250000 set(125000) 0.42500 ns/op 0.47500 ns/op 0.89
Array 250000 iterate all - loop 80.821 us/op 86.346 us/op 0.94
phase0 afterProcessEpoch - 250000 vs - 7PWei 40.667 ms/op 44.942 ms/op 0.90
Array.fill - length 1000000 3.6531 ms/op 4.1792 ms/op 0.87
Array push - length 1000000 12.120 ms/op 15.374 ms/op 0.79
Array.get 0.26571 ns/op 0.28768 ns/op 0.92
Uint8Array.get 0.43105 ns/op 0.45774 ns/op 0.94
phase0 beforeProcessEpoch - 250000 vs - 7PWei 15.906 ms/op 18.704 ms/op 0.85
altair processEpoch - mainnet_e81889 273.99 ms/op 257.51 ms/op 1.06
mainnet_e81889 - altair beforeProcessEpoch 15.877 ms/op 21.940 ms/op 0.72
mainnet_e81889 - altair processJustificationAndFinalization 5.5910 us/op 5.4560 us/op 1.02
mainnet_e81889 - altair processInactivityUpdates 3.9731 ms/op 4.5315 ms/op 0.88
mainnet_e81889 - altair processRewardsAndPenalties 41.908 ms/op 37.416 ms/op 1.12
mainnet_e81889 - altair processRegistryUpdates 684.00 ns/op 759.00 ns/op 0.90
mainnet_e81889 - altair processSlashings 171.00 ns/op 184.00 ns/op 0.93
mainnet_e81889 - altair processEth1DataReset 167.00 ns/op 181.00 ns/op 0.92
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.1613 ms/op 1.2709 ms/op 0.91
mainnet_e81889 - altair processSlashingsReset 1.4430 us/op 897.00 ns/op 1.61
mainnet_e81889 - altair processRandaoMixesReset 1.1270 us/op 1.1590 us/op 0.97
mainnet_e81889 - altair processHistoricalRootsUpdate 177.00 ns/op 180.00 ns/op 0.98
mainnet_e81889 - altair processParticipationFlagUpdates 500.00 ns/op 538.00 ns/op 0.93
mainnet_e81889 - altair processSyncCommitteeUpdates 130.00 ns/op 143.00 ns/op 0.91
mainnet_e81889 - altair afterProcessEpoch 41.838 ms/op 45.468 ms/op 0.92
capella processEpoch - mainnet_e217614 926.16 ms/op 927.25 ms/op 1.00
mainnet_e217614 - capella beforeProcessEpoch 61.690 ms/op 70.467 ms/op 0.88
mainnet_e217614 - capella processJustificationAndFinalization 5.4540 us/op 5.7090 us/op 0.96
mainnet_e217614 - capella processInactivityUpdates 14.682 ms/op 16.256 ms/op 0.90
mainnet_e217614 - capella processRewardsAndPenalties 188.85 ms/op 194.99 ms/op 0.97
mainnet_e217614 - capella processRegistryUpdates 7.5160 us/op 6.9020 us/op 1.09
mainnet_e217614 - capella processSlashings 183.00 ns/op 182.00 ns/op 1.01
mainnet_e217614 - capella processEth1DataReset 183.00 ns/op 182.00 ns/op 1.01
mainnet_e217614 - capella processEffectiveBalanceUpdates 4.1539 ms/op 4.3251 ms/op 0.96
mainnet_e217614 - capella processSlashingsReset 858.00 ns/op 926.00 ns/op 0.93
mainnet_e217614 - capella processRandaoMixesReset 1.1550 us/op 1.2040 us/op 0.96
mainnet_e217614 - capella processHistoricalRootsUpdate 182.00 ns/op 185.00 ns/op 0.98
mainnet_e217614 - capella processParticipationFlagUpdates 533.00 ns/op 533.00 ns/op 1.00
mainnet_e217614 - capella afterProcessEpoch 113.90 ms/op 118.68 ms/op 0.96
phase0 processEpoch - mainnet_e58758 341.86 ms/op 277.52 ms/op 1.23
mainnet_e58758 - phase0 beforeProcessEpoch 80.854 ms/op 73.608 ms/op 1.10
mainnet_e58758 - phase0 processJustificationAndFinalization 6.0360 us/op 5.6390 us/op 1.07
mainnet_e58758 - phase0 processRewardsAndPenalties 37.291 ms/op 36.338 ms/op 1.03
mainnet_e58758 - phase0 processRegistryUpdates 3.0380 us/op 3.2690 us/op 0.93
mainnet_e58758 - phase0 processSlashings 169.00 ns/op 182.00 ns/op 0.93
mainnet_e58758 - phase0 processEth1DataReset 168.00 ns/op 180.00 ns/op 0.93
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.1934 ms/op 1.2074 ms/op 0.99
mainnet_e58758 - phase0 processSlashingsReset 848.00 ns/op 948.00 ns/op 0.89
mainnet_e58758 - phase0 processRandaoMixesReset 1.1790 us/op 1.2420 us/op 0.95
mainnet_e58758 - phase0 processHistoricalRootsUpdate 177.00 ns/op 183.00 ns/op 0.97
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.0990 us/op 914.00 ns/op 1.20
mainnet_e58758 - phase0 afterProcessEpoch 35.769 ms/op 51.837 ms/op 0.69
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.3355 ms/op 1.3705 ms/op 0.97
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.9395 ms/op 2.1094 ms/op 0.92
altair processInactivityUpdates - 250000 normalcase 18.796 ms/op 18.399 ms/op 1.02
altair processInactivityUpdates - 250000 worstcase 22.009 ms/op 18.324 ms/op 1.20
phase0 processRegistryUpdates - 250000 normalcase 5.5820 us/op 6.5930 us/op 0.85
phase0 processRegistryUpdates - 250000 badcase_full_deposits 301.94 us/op 262.16 us/op 1.15
phase0 processRegistryUpdates - 250000 worstcase 0.5 122.05 ms/op 99.970 ms/op 1.22
altair processRewardsAndPenalties - 250000 normalcase 31.274 ms/op 31.964 ms/op 0.98
altair processRewardsAndPenalties - 250000 worstcase 35.272 ms/op 25.686 ms/op 1.37
phase0 getAttestationDeltas - 250000 normalcase 6.9432 ms/op 7.3091 ms/op 0.95
phase0 getAttestationDeltas - 250000 worstcase 5.8742 ms/op 6.7667 ms/op 0.87
phase0 processSlashings - 250000 worstcase 76.998 us/op 94.775 us/op 0.81
altair processSyncCommitteeUpdates - 250000 10.838 ms/op 11.086 ms/op 0.98
BeaconState.hashTreeRoot - No change 222.00 ns/op 216.00 ns/op 1.03
BeaconState.hashTreeRoot - 1 full validator 97.200 us/op 75.884 us/op 1.28
BeaconState.hashTreeRoot - 32 full validator 830.76 us/op 926.33 us/op 0.90
BeaconState.hashTreeRoot - 512 full validator 11.504 ms/op 10.658 ms/op 1.08
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 122.61 us/op 95.085 us/op 1.29
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.2697 ms/op 1.5231 ms/op 0.83
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 22.268 ms/op 26.265 ms/op 0.85
BeaconState.hashTreeRoot - 1 balances 100.23 us/op 85.386 us/op 1.17
BeaconState.hashTreeRoot - 32 balances 991.79 us/op 832.18 us/op 1.19
BeaconState.hashTreeRoot - 512 balances 9.8390 ms/op 7.6876 ms/op 1.28
BeaconState.hashTreeRoot - 250000 balances 182.12 ms/op 152.85 ms/op 1.19
aggregationBits - 2048 els - zipIndexesInBitList 21.079 us/op 22.031 us/op 0.96
byteArrayEquals 32 52.712 ns/op 54.983 ns/op 0.96
Buffer.compare 32 16.668 ns/op 17.443 ns/op 0.96
byteArrayEquals 1024 1.5544 us/op 1.6305 us/op 0.95
Buffer.compare 1024 25.033 ns/op 26.094 ns/op 0.96
byteArrayEquals 16384 24.743 us/op 25.923 us/op 0.95
Buffer.compare 16384 313.71 ns/op 208.60 ns/op 1.50
byteArrayEquals 123687377 196.04 ms/op 185.69 ms/op 1.06
Buffer.compare 123687377 7.5794 ms/op 6.0631 ms/op 1.25
byteArrayEquals 32 - diff last byte 53.050 ns/op 50.228 ns/op 1.06
Buffer.compare 32 - diff last byte 17.399 ns/op 16.376 ns/op 1.06
byteArrayEquals 1024 - diff last byte 1.6564 us/op 1.5154 us/op 1.09
Buffer.compare 1024 - diff last byte 25.708 ns/op 24.905 ns/op 1.03
byteArrayEquals 16384 - diff last byte 25.515 us/op 24.149 us/op 1.06
Buffer.compare 16384 - diff last byte 189.26 ns/op 195.89 ns/op 0.97
byteArrayEquals 123687377 - diff last byte 205.46 ms/op 191.22 ms/op 1.07
Buffer.compare 123687377 - diff last byte 9.6382 ms/op 6.1418 ms/op 1.57
byteArrayEquals 32 - random bytes 5.2160 ns/op 5.1350 ns/op 1.02
Buffer.compare 32 - random bytes 17.460 ns/op 17.370 ns/op 1.01
byteArrayEquals 1024 - random bytes 5.4030 ns/op 5.1400 ns/op 1.05
Buffer.compare 1024 - random bytes 17.384 ns/op 17.361 ns/op 1.00
byteArrayEquals 16384 - random bytes 5.2410 ns/op 5.1560 ns/op 1.02
Buffer.compare 16384 - random bytes 17.427 ns/op 17.354 ns/op 1.00
byteArrayEquals 123687377 - random bytes 7.1100 ns/op 6.5000 ns/op 1.09
Buffer.compare 123687377 - random bytes 18.530 ns/op 18.590 ns/op 1.00
regular array get 100000 times 41.748 us/op 32.838 us/op 1.27
wrappedArray get 100000 times 33.557 us/op 32.784 us/op 1.02
arrayWithProxy get 100000 times 12.996 ms/op 13.079 ms/op 0.99
ssz.Root.equals 46.748 ns/op 46.137 ns/op 1.01
byteArrayEquals 47.006 ns/op 45.252 ns/op 1.04
Buffer.compare 10.724 ns/op 10.329 ns/op 1.04
processSlot - 1 slots 11.402 us/op 10.277 us/op 1.11
processSlot - 32 slots 3.5150 ms/op 2.1980 ms/op 1.60
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 3.5140 ms/op 2.8019 ms/op 1.25
getCommitteeAssignments - req 1 vs - 250000 vc 2.3112 ms/op 2.1399 ms/op 1.08
getCommitteeAssignments - req 100 vs - 250000 vc 4.4601 ms/op 4.1545 ms/op 1.07
getCommitteeAssignments - req 1000 vs - 250000 vc 4.7380 ms/op 4.4264 ms/op 1.07
findModifiedValidators - 10000 modified validators 790.08 ms/op 724.86 ms/op 1.09
findModifiedValidators - 1000 modified validators 769.90 ms/op 704.58 ms/op 1.09
findModifiedValidators - 100 modified validators 212.78 ms/op 243.23 ms/op 0.87
findModifiedValidators - 10 modified validators 146.66 ms/op 252.31 ms/op 0.58
findModifiedValidators - 1 modified validators 163.42 ms/op 182.54 ms/op 0.90
findModifiedValidators - no difference 158.68 ms/op 148.40 ms/op 1.07
compare ViewDUs 6.4644 s/op 5.9473 s/op 1.09
compare each validator Uint8Array 1.8703 s/op 1.3166 s/op 1.42
compare ViewDU to Uint8Array 1.2436 s/op 1.0055 s/op 1.24
migrate state 1000000 validators, 24 modified, 0 new 928.26 ms/op 781.97 ms/op 1.19
migrate state 1000000 validators, 1700 modified, 1000 new 1.1895 s/op 1.1197 s/op 1.06
migrate state 1000000 validators, 3400 modified, 2000 new 1.3942 s/op 1.1424 s/op 1.22
migrate state 1500000 validators, 24 modified, 0 new 861.37 ms/op 893.60 ms/op 0.96
migrate state 1500000 validators, 1700 modified, 1000 new 1.0365 s/op 1.1405 s/op 0.91
migrate state 1500000 validators, 3400 modified, 2000 new 1.3031 s/op 1.2957 s/op 1.01
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 5.1100 ns/op 4.3400 ns/op 1.18
state getBlockRootAtSlot - 250000 vs - 7PWei 756.74 ns/op 878.76 ns/op 0.86
naive computeProposerIndex 100000 validators 48.259 ms/op 59.654 ms/op 0.81
computeProposerIndex 100000 validators 1.4854 ms/op 1.5724 ms/op 0.94
naiveGetNextSyncCommitteeIndices 1000 validators 7.3309 s/op 7.9128 s/op 0.93
getNextSyncCommitteeIndices 1000 validators 105.52 ms/op 115.08 ms/op 0.92
naiveGetNextSyncCommitteeIndices 10000 validators 7.6556 s/op 9.0412 s/op 0.85
getNextSyncCommitteeIndices 10000 validators 107.25 ms/op 167.58 ms/op 0.64
naiveGetNextSyncCommitteeIndices 100000 validators 7.8644 s/op 10.188 s/op 0.77
getNextSyncCommitteeIndices 100000 validators 108.02 ms/op 138.03 ms/op 0.78
naive computeShuffledIndex 100000 validators 25.199 s/op 36.010 s/op 0.70
cached computeShuffledIndex 100000 validators 540.70 ms/op 777.24 ms/op 0.70
naive computeShuffledIndex 2000000 validators 538.19 s/op 492.74 s/op 1.09
cached computeShuffledIndex 2000000 validators 32.621 s/op 32.514 s/op 1.00
computeProposers - vc 250000 612.32 us/op 628.09 us/op 0.97
computeEpochShuffling - vc 250000 41.762 ms/op 42.206 ms/op 0.99
getNextSyncCommittee - vc 250000 10.455 ms/op 10.433 ms/op 1.00
computeSigningRoot for AttestationData 21.379 us/op 22.561 us/op 0.95
hash AttestationData serialized data then Buffer.toString(base64) 1.5744 us/op 1.5528 us/op 1.01
toHexString serialized data 1.0902 us/op 1.1104 us/op 0.98
Buffer.toString(base64) 158.28 ns/op 136.61 ns/op 1.16
nodejs block root to RootHex using toHex 150.35 ns/op 126.95 ns/op 1.18
nodejs block root to RootHex using toRootHex 87.336 ns/op 82.415 ns/op 1.06
nodejs fromhex(blob) 114.96 ms/op 110.09 ms/op 1.04
nodejs fromHexInto(blob) 97.374 ms/op 95.565 ms/op 1.02
browser block root to RootHex using the deprecated toHexString 207.08 ns/op 204.70 ns/op 1.01
browser block root to RootHex using toHex 171.44 ns/op 165.54 ns/op 1.04
browser block root to RootHex using toRootHex 160.47 ns/op 155.24 ns/op 1.03
browser fromHexInto(blob) 823.99 us/op 799.81 us/op 1.03
browser fromHex(blob) 792.01 ms/op 764.08 ms/op 1.04

by benchmarkbot/action

@codecov
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
@wemeetagain wemeetagain changed the title feat: add lmdb database from lodestar-bun feat: add lmdb and sqlite backend Oct 13, 2025
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.

3 participants