From a6682c7d36c97dff2c5d2b9e04bb8e4f7828857f Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Mon, 22 Jul 2024 20:31:24 +0200 Subject: [PATCH 1/2] evm: opcode benchmarks --- packages/evm/test/opcodes.bench.ts | 70 ++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 packages/evm/test/opcodes.bench.ts diff --git a/packages/evm/test/opcodes.bench.ts b/packages/evm/test/opcodes.bench.ts new file mode 100644 index 00000000000..063a70d1275 --- /dev/null +++ b/packages/evm/test/opcodes.bench.ts @@ -0,0 +1,70 @@ +import { Chain, Common, Hardfork } from '@ethereumjs/common' +import { Address } from '@ethereumjs/util' +import { hexToBytes } from 'ethereum-cryptography/utils' +import { bench, describe } from 'vitest' + +import { stackDelta } from '../src/eof/stackDelta.js' +import { createEVM } from '../src/index.js' + +const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Cancun }) + +function getOpcode(name: string) { + for (const key in stackDelta) { + const op = stackDelta[key] + if (op.name === name) { + return key + } + } + throw new Error(`Opcode ${name} not found`) +} + +const eofOpcodes = [ + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xec, 0xee, 0xd0, 0xd1, 0xd2, 0xd3, 0xe6, 0xe7, 0xe8, 0xf7, + 0xf8, 0xf9, 0xfb, +] + +// NOTE: stackDelta only contains EOF opcodes! +function generateCode(opcode: number) { + const stackInfo = stackDelta[opcode] + if (eofOpcodes.includes(opcode) || stackInfo === undefined || stackInfo.intermediates) { + return + } + const JUMP = 0x56 + const JUMPDEST = 0x5b + const PUSH0 = getOpcode('PUSH0') + const POP = getOpcode('POP') + const code = new Uint8Array([ + JUMPDEST, + ...Array(stackInfo.inputs).fill(PUSH0), + opcode, + ...Array(stackInfo.outputs).fill(POP), + PUSH0, + JUMP, + ]) + return code +} + +const codeAddress = new Address(hexToBytes('0x' + 'ee'.repeat(20))) + +// Note: vitest will run this sequentially and it looks (in the output) like it does nothing +// It will run 100+ benchmarks sequentially +// This takes some time, so patience is the key! +describe('EVM opcode speed', async () => { + for (let opcode = 1; opcode <= 255; opcode++) { + const code = generateCode(opcode) + if (code !== undefined) { + const evm = await createEVM({ common }) + await evm.stateManager.putContractCode(codeAddress, code) + bench( + `Benchmark for: ${stackDelta[opcode].name}`, + async () => { + await evm.runCall({ + to: codeAddress, + gasLimit: BigInt(1_000_000), + }) + }, + {} + ) + } + } +}) From f5a116d2a92817adcb44ea928150810b5ec6db63 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Mon, 22 Jul 2024 20:40:50 +0200 Subject: [PATCH 2/2] evm: move benchmark to benchmarks folder --- packages/evm/{test => benchmarks}/opcodes.bench.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/evm/{test => benchmarks}/opcodes.bench.ts (100%) diff --git a/packages/evm/test/opcodes.bench.ts b/packages/evm/benchmarks/opcodes.bench.ts similarity index 100% rename from packages/evm/test/opcodes.bench.ts rename to packages/evm/benchmarks/opcodes.bench.ts