import {itBench, setBenchOpts} from "@dapplion/benchmark"; import {phase0, ssz} from "@lodestar/types"; import {ContainerType, ListCompositeType} from "@chainsafe/ssz"; import {newFilledArray, BeaconStateAllForks} from "@lodestar/state-transition"; import {fastSerializeEth1Data, pickEth1Vote} from "../../../src/eth1/utils/eth1Vote.js"; describe("eth1 / pickEth1Vote", () => { const ETH1_FOLLOW_DISTANCE_MAINNET = 2048; const EPOCHS_PER_ETH1_VOTING_PERIOD_MAINNET = 64; const SLOTS_PER_EPOCH_MAINNET = 32; const eth1DataVotesLimit = EPOCHS_PER_ETH1_VOTING_PERIOD_MAINNET * SLOTS_PER_EPOCH_MAINNET; const stateMainnetType = new ContainerType({ eth1DataVotes: new ListCompositeType(ssz.phase0.Eth1Data, eth1DataVotesLimit), }); const stateNoVotes = stateMainnetType.defaultViewDU(); const stateMaxVotes = stateMainnetType.defaultViewDU(); // Must convert all instances to create a cache stateMaxVotes.eth1DataVotes = ssz.phase0.Eth1DataVotes.toViewDU( newFilledArray(eth1DataVotesLimit, { depositRoot: Buffer.alloc(32, 0xdd), // All votes are the same depositCount: 1e6, blockHash: Buffer.alloc(32, 0xdd), }) ); stateMaxVotes.commit(); // votesToConsider range: // lte: periodStart - SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE, // gte: periodStart - SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE * 2, const votesToConsider = Array.from({length: ETH1_FOLLOW_DISTANCE_MAINNET}, (_, i) => ({ depositRoot: Buffer.alloc(32, 0xdd), // Each eth1Data is different depositCount: 1e6 + i, blockHash: Buffer.alloc(32, 0xdd), })); itBench("pickEth1Vote - no votes", () => { pickEth1Vote((stateNoVotes as unknown) as BeaconStateAllForks, votesToConsider); }); itBench("pickEth1Vote - max votes", () => { pickEth1Vote((stateMaxVotes as unknown) as BeaconStateAllForks, votesToConsider); }); }); // Results in Linux Feb 2022 // // eth1 / pickEth1Vote serializers // ✓ pickEth1Vote - Eth1Data hashTreeRoot value x2048 58.45559 ops/s 17.10700 ms/op - 45 runs 1.27 s // ✓ pickEth1Vote - Eth1Data hashTreeRoot tree x2048 122.1150 ops/s 8.189003 ms/op - 65 runs 1.75 s // ✓ pickEth1Vote - Eth1Data fastSerialize value x2048 533.9807 ops/s 1.872727 ms/op - 272 runs 1.01 s // ✓ pickEth1Vote - Eth1Data fastSerialize tree x2048 59.49406 ops/s 16.80840 ms/op - 60 runs 1.51 s describe("eth1 / pickEth1Vote serializers", () => { setBenchOpts({noThreshold: true}); const ETH1_FOLLOW_DISTANCE_MAINNET = 2048; const eth1DataValue: phase0.Eth1Data = { depositRoot: Buffer.alloc(32, 0xdd), depositCount: 1e6, blockHash: Buffer.alloc(32, 0xdd), }; const eth1DataTree = ssz.phase0.Eth1Data.toViewDU(eth1DataValue); itBench(`pickEth1Vote - Eth1Data hashTreeRoot value x${ETH1_FOLLOW_DISTANCE_MAINNET}`, () => { for (let i = 0; i < ETH1_FOLLOW_DISTANCE_MAINNET; i++) { ssz.phase0.Eth1Data.hashTreeRoot(eth1DataValue); } }); // Create new copies of eth1DataTree to drop the hashing cache itBench({ id: `pickEth1Vote - Eth1Data hashTreeRoot tree x${ETH1_FOLLOW_DISTANCE_MAINNET}`, beforeEach: () => Array.from({length: ETH1_FOLLOW_DISTANCE_MAINNET}, () => ssz.phase0.Eth1Data.toViewDU(eth1DataValue)), fn: (eth1DataTrees) => { for (let i = 0; i < eth1DataTrees.length; i++) { ssz.phase0.Eth1Data.hashTreeRoot(eth1DataTrees[i]); } }, }); itBench(`pickEth1Vote - Eth1Data fastSerialize value x${ETH1_FOLLOW_DISTANCE_MAINNET}`, () => { for (let i = 0; i < ETH1_FOLLOW_DISTANCE_MAINNET; i++) { fastSerializeEth1Data(eth1DataValue); } }); itBench(`pickEth1Vote - Eth1Data fastSerialize tree x${ETH1_FOLLOW_DISTANCE_MAINNET}`, () => { for (let i = 0; i < ETH1_FOLLOW_DISTANCE_MAINNET; i++) { fastSerializeEth1Data(eth1DataTree); } }); });