Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 16 additions & 27 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions packages/mpt/benchmarks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { MapDB } from '@ethereumjs/util'
import { keccak_256 as nobleKeccak } from '@noble/hashes/sha3.js'
import { keccak_256 as unrolledKeccak } from 'unrolled-nbl-hashes-sha3'
import { LevelDB } from './engines/level'
import { createSuite } from './suite'

createSuite(new MapDB())
createSuite(new LevelDB())
// Run with noble keccak (baseline)
createSuite(new MapDB(), nobleKeccak, '[noble] ')
createSuite(new LevelDB(), nobleKeccak, '[noble] ')

// Run with unrolled keccak
createSuite(new MapDB(), unrolledKeccak, '[unrolled] ')
createSuite(new LevelDB(), unrolledKeccak, '[unrolled] ')
30 changes: 30 additions & 0 deletions packages/mpt/benchmarks/keccak.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { keccak_256 as nobleKeccak } from '@noble/hashes/sha3.js'
//@ts-expect-error - package has no types...
import { mark } from 'micro-bmark' // cspell:disable-line
import { keccak_256 as unrolledKeccak } from 'unrolled-nbl-hashes-sha3'

const ITERATIONS = 50000

async function main() {
for (const size of [32, 100, 500, 2000]) {
const input = new Uint8Array(size)
for (let i = 0; i < size; i++) input[i] = i & 0xff

await mark(`noble keccak256 (${size} bytes)`, ITERATIONS, () => {
nobleKeccak(input)
})

await mark(`unrolled keccak256 (${size} bytes)`, ITERATIONS, () => {
unrolledKeccak(input)
})
}

// Verify output equivalence
const testInput = new Uint8Array([1, 2, 3, 4, 5])
const nobleResult = nobleKeccak(testInput)
const unrolledResult = unrolledKeccak(testInput)
const match = nobleResult.every((b: number, i: number) => b === unrolledResult[i])
console.log(`\nOutput equivalence check: ${match ? 'PASS' : 'FAIL'}`)
}

main()
25 changes: 14 additions & 11 deletions packages/mpt/benchmarks/suite.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { keccak_256 } from '@noble/hashes/sha3.js'
//@ts-expect-error - package has no types...
import { logMem, mark, run } from 'micro-bmark' // cspell:disable-line
import { mark, utils } from 'micro-bmark' // cspell:disable-line

import { MerklePatriciaTrie } from '../dist/cjs/index.js'
import { keys } from './keys'

import type { DB } from '@ethereumjs/util'

export function createSuite(db: DB<string, string>) {
const trie = new MerklePatriciaTrie({ db })
const checkpointTrie = new MerklePatriciaTrie({ db })
export function createSuite(
db: DB<string, string>,
hashFn: (msg: Uint8Array) => Uint8Array = keccak_256,
label: string = '',
) {
const trie = new MerklePatriciaTrie({ db, useKeyHashingFunction: hashFn })
const checkpointTrie = new MerklePatriciaTrie({ db, useKeyHashingFunction: hashFn })

const ROUNDS = 1000
const KEY_SIZE = 32

run(async () => {
;(async () => {
// random.ts
// Test ID is defined as: `pair_count`-`era_size`-`key_size`-`value_type`
// where value_type = symmetric ? 'mir' : 'ran'
Expand All @@ -27,11 +30,11 @@ export function createSuite(db: DB<string, string>) {
['1k-1k-32-ran', 1000, false],
['1k-1k-32-mir', 1000, true],
]) {
await mark(title, async () => {
await mark(`${label}${title}`, async () => {
let key = new Uint8Array(KEY_SIZE)

for (let i = 0; i <= ROUNDS; i++) {
key = keccak_256(key)
key = hashFn(key)

if (symmetric) {
await trie.put(key, key)
Expand All @@ -49,13 +52,13 @@ export function createSuite(db: DB<string, string>) {
// References:
// https://gist.github.com/heikoheiko/0fa2b322560ba7794f22/
for (const samples of [100, 500, 1000, 5000]) {
await mark(`Checkpointing: ${samples} iterations`, samples, async (i: number) => {
await mark(`${label}Checkpointing: ${samples} iterations`, samples, async (i: number) => {
checkpointTrie.checkpoint()
await checkpointTrie.put(keys[i], keys[i])
await checkpointTrie.commit()
})
}

logMem()
})
utils.logMem()
})()
}
3 changes: 2 additions & 1 deletion packages/mpt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"level": "^9.0.0",
"lmdb": "^3.2.6",
"memory-level": "^3.0.0",
"micro-bmark": "0.4.0"
"micro-bmark": "0.4.0",
"unrolled-nbl-hashes-sha3": "^0.1.1"
},
"engines": {
"node": ">=20"
Expand Down
Loading