Apply perf OOM issue fix to epoch benchmarks (#3026)

* Add yieldEventLoopAfterEach to all benchmarks that change state a lot

* Set global opts to benchmark with a config file

* Use noThreshold option for clarity
This commit is contained in:
Lion - dapplion
2021-08-27 02:47:31 +02:00
committed by GitHub
parent b1353af356
commit 3a1c8e9083
32 changed files with 77 additions and 102 deletions

View File

@@ -1,4 +1,10 @@
# Mocha opts
colors: true
require:
- ts-node/register
- packages/lodestar/test/setupBLS.ts
# benchmark opts
threshold: 3
maxMs: 60_000
minRuns: 10

View File

@@ -47,7 +47,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# benchmark options
BENCHMARK_S3: true
BENCHMARK_threshold: 3
# S3 credentials
S3_ACCESS_KEY: ${{ secrets.S3_BENCH_LODESTAR_ACCESS_KEY }}
S3_SECRET_KEY: ${{ secrets.S3_BENCH_LODESTAR_SECRET_KEY }}

View File

@@ -32,7 +32,7 @@
"check-readme": "lerna run check-readme"
},
"devDependencies": {
"@dapplion/benchmark": "^0.2.0",
"@dapplion/benchmark": "^0.2.2",
"@types/chai": "4.2.0",
"@types/chai-as-promised": "^7.1.2",
"@types/mocha": "^8.0.3",

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {phase0, ssz} from "@chainsafe/lodestar-types";
import {TreeBacked} from "@chainsafe/ssz";
import {generatePerformanceStatePhase0, getPubkeys, numValidators} from "../util";
@@ -7,8 +7,6 @@ import {unshuffleList} from "../../../src";
// Test cost of hashing state after some modifications
describe("state hashTreeRoot", () => {
setBenchOpts({maxMs: 60 * 1000});
const vc = numValidators;
const indicesShuffled: number[] = [];
let stateOg: TreeBacked<phase0.BeaconState>;
@@ -26,7 +24,7 @@ describe("state hashTreeRoot", () => {
const validator: phase0.Validator = ssz.phase0.Validator.defaultValue();
const balance = BigInt(31e9);
const testCases: {id: string; track?: boolean; fn: (state: TreeBacked<phase0.BeaconState>) => void}[] = [
const testCases: {id: string; noTrack?: boolean; fn: (state: TreeBacked<phase0.BeaconState>) => void}[] = [
{
id: "No change",
fn: () => {
@@ -40,7 +38,7 @@ describe("state hashTreeRoot", () => {
const idxs = indicesShuffled.slice(0, count);
testCases.push({
id: `${count} full validator`,
track: count >= 512,
noTrack: count < 512,
fn: (state) => {
for (const i of idxs) state.validators[i] = validator;
},
@@ -51,7 +49,7 @@ describe("state hashTreeRoot", () => {
const idxs = indicesShuffled.slice(0, count);
testCases.push({
id: `${count} validator.effectiveBalance`,
track: count >= 512,
noTrack: count < 512,
fn: (state) => {
for (const i of idxs) state.validators[i].effectiveBalance = balance;
},
@@ -63,17 +61,17 @@ describe("state hashTreeRoot", () => {
const idxs = indicesShuffled.slice(0, count);
testCases.push({
id: `${count} balances`,
track: count >= 512,
noTrack: count < 512,
fn: (state) => {
for (const i of idxs) state.balances[i] = balance;
},
});
}
for (const {id, track, fn} of testCases) {
for (const {id, noTrack, fn} of testCases) {
itBench<TreeBacked<phase0.BeaconState>, TreeBacked<phase0.BeaconState>>({
id: `state hashTreeRoot - ${id}`,
threshold: !track ? Infinity : undefined,
noThreshold: noTrack,
beforeEach: () => {
fn(stateOg);
return stateOg;

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {generatePerfTestCachedStatePhase0} from "../../util";
import {processSlot} from "../../../../src/allForks/slot";
import {State} from "../../types";
@@ -6,8 +6,6 @@ import {State} from "../../types";
// Test advancing through an empty slot, without any epoch transition
describe("processSlot", () => {
setBenchOpts({maxMs: 60 * 1000});
for (const slotCount of [1, 32]) {
itBench<State, State>({
id: `processSlot - ${slotCount} slots`,

View File

@@ -1,5 +1,5 @@
import {Epoch} from "@chainsafe/lodestar-types";
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {allForks, computeEpochAtSlot} from "../../../../src";
import {generatePerfTestCachedStatePhase0, numValidators} from "../../util";
@@ -22,8 +22,6 @@ describe("epochCtx.getCommitteeAssignments", () => {
if (state.validators.length !== numValidators) throw Error("constant numValidators is wrong");
});
setBenchOpts({maxMs: 10 * 1000});
// the new way of getting attester duties
for (const reqCount of [1, 100, 1000]) {
const validatorCount = numValidators;
@@ -34,7 +32,7 @@ describe("epochCtx.getCommitteeAssignments", () => {
itBench({
id: `getCommitteeAssignments - req ${reqCount} vs - ${validatorCount} vc`,
// Only run for 1000 in CI to ensure performance does not degrade
threshold: reqCount < 1000 ? Infinity : undefined,
noThreshold: reqCount < 1000,
fn: () => {
state.epochCtx.getCommitteeAssignments(epoch, indices);
},

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {
ACTIVE_PRESET,
MAX_ATTESTATIONS,
@@ -66,8 +66,6 @@ import {StateBlock} from "../../types";
//
describe("altair processBlock", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
if (ACTIVE_PRESET !== PresetName.mainnet) {
throw Error(`ACTIVE_PRESET ${ACTIVE_PRESET} must be mainnet`);
}

View File

@@ -9,7 +9,9 @@ const slot = computeStartSlotAtEpoch(epoch) - 1;
const stateId = `${network}_e${epoch}`;
describe(`altair processEpoch - ${stateId}`, () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
setBenchOpts({
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
});
const stateOg = beforeValue(async () => {
const state = await getNetworkCachedState(network, slot, 300_000);
@@ -19,6 +21,7 @@ describe(`altair processEpoch - ${stateId}`, () => {
itBench({
id: `altair processEpoch - ${stateId}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
beforeEach: () => stateOg.value.clone() as CachedBeaconState<allForks.BeaconState>,
fn: (state) => {
const epochProcess = allForks.beforeProcessEpoch(state);
@@ -31,7 +34,7 @@ describe(`altair processEpoch - ${stateId}`, () => {
// Only in local environment compute a full breakdown of the cost of each step
describe(`altair processEpoch steps - ${stateId}`, () => {
setBenchOpts({threshold: Infinity, minRuns: 10});
setBenchOpts({noThreshold: true});
benchmarkAltairEpochSteps(stateOg, stateId);
});

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {altair} from "../../../../src";
import {FlagFactors, generateBalanceDeltasEpochProcess} from "../../phase0/epoch/util";
import {StateAltairEpoch} from "../../types";
@@ -20,8 +20,6 @@ import {mutateInactivityScores} from "./util";
// - all inactivityScores > 0
describe("altair processInactivityUpdates", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
const vc = numValidators;
const testCases: {id: string; isInInactivityLeak: boolean; flagFactors: FlagFactors; factorWithPositive: number}[] = [
@@ -42,6 +40,7 @@ describe("altair processInactivityUpdates", () => {
for (const {id, isInInactivityLeak, flagFactors, factorWithPositive} of testCases) {
itBench<StateAltairEpoch, StateAltairEpoch>({
id: `altair processInactivityUpdates - ${vc} ${id}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
before: () => {
const state = generatePerfTestCachedStateAltair({goBackOneSlot: true});
const epochProcess = generateBalanceDeltasEpochProcess(state, isInInactivityLeak, flagFactors);

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {altair} from "../../../../src";
import {StateAltair} from "../../types";
import {generatePerfTestCachedStateAltair, numValidators} from "../../util";
@@ -6,12 +6,11 @@ import {generatePerfTestCachedStateAltair, numValidators} from "../../util";
// PERF: Cost = 'proportional' to $VALIDATOR_COUNT. Just copies a tree and recreates another
describe("altair processParticipationFlagUpdates", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
const vc = numValidators;
itBench<StateAltair, StateAltair>({
id: `altair processParticipationFlagUpdates - ${vc} anycase`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
before: () => generatePerfTestCachedStateAltair({goBackOneSlot: true}),
beforeEach: (state) => state.clone(),
fn: (state) => altair.processParticipationFlagUpdates(state),

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {altair} from "../../../../src";
import {generatePerfTestCachedStateAltair, numValidators} from "../../util";
import {FlagFactors, generateBalanceDeltasEpochProcess} from "../../phase0/epoch/util";
@@ -13,8 +13,6 @@ import {mutateInactivityScores} from "./util";
// inactivityScore > 0
describe("altair processRewardsAndPenalties", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
const vc = numValidators;
const testCases: {id: string; isInInactivityLeak: boolean; flagFactors: FlagFactors; factorWithPositive: number}[] = [
{
@@ -43,6 +41,7 @@ describe("altair processRewardsAndPenalties", () => {
for (const {id, isInInactivityLeak, flagFactors, factorWithPositive} of testCases) {
itBench<StateAltairEpoch, StateAltairEpoch>({
id: `altair processRewardsAndPenalties - ${vc} ${id}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
before: () => {
const state = generatePerfTestCachedStateAltair({goBackOneSlot: true});
const epochProcess = generateBalanceDeltasEpochProcess(state, isInInactivityLeak, flagFactors);

View File

@@ -1,16 +1,15 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {StateAltair} from "../../types";
import {generatePerfTestCachedStateAltair, numValidators} from "../../util";
// PERF: Cost = once per epoch compute committee, proportional to $VALIDATOR_COUNT
describe("altair processSyncCommitteeUpdates", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
const vc = numValidators;
itBench<StateAltair, StateAltair>({
id: `altair processSyncCommitteeUpdates - ${vc}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
before: () => generatePerfTestCachedStateAltair({goBackOneSlot: true}),
beforeEach: (state) => state.clone(),
fn: (state) => state.rotateSyncCommittee(),

View File

@@ -46,7 +46,7 @@ const runsFactor = 1000;
describe("Tree (persistent-merkle-tree)", () => {
// Don't track regressions in CI
setBenchOpts({maxMs: 10 * 1000, threshold: Infinity});
setBenchOpts({noThreshold: true});
const d = 40;
const gih = toGindex(d, BigInt(ih));
@@ -58,7 +58,7 @@ describe("Tree (persistent-merkle-tree)", () => {
tree = getTree(d, n);
});
itBench({id: `Tree ${d} ${n} create`, timeout: 60_000}, () => {
itBench({id: `Tree ${d} ${n} create`, timeoutBench: 60_000}, () => {
getTree(d, n);
});
@@ -101,7 +101,7 @@ describe("Tree (persistent-merkle-tree)", () => {
describe("MutableVector", () => {
// Don't track regressions in CI
setBenchOpts({maxMs: 10 * 1000, threshold: Infinity});
setBenchOpts({noThreshold: true});
let items: number[];
let mutableVector: MutableVector<number>;
@@ -143,7 +143,7 @@ describe("MutableVector", () => {
describe("Array", () => {
// Don't track regressions in CI
setBenchOpts({maxMs: 10 * 1000, threshold: Infinity});
setBenchOpts({noThreshold: true});
let arr: number[];

View File

@@ -5,7 +5,7 @@ import {BitList, List, readonlyValues, TreeBacked} from "@chainsafe/ssz";
import {zipIndexesCommitteeBits} from "../../../src";
describe("aggregationBits", () => {
setBenchOpts({maxMs: 60 * 1000, threshold: Infinity});
setBenchOpts({noThreshold: true});
const len = MAX_VALIDATORS_PER_COMMITTEE;
const idPrefix = `aggregationBits - ${len} els`;

View File

@@ -10,7 +10,7 @@ import {byteArrayEquals, fromHexString} from "@chainsafe/ssz";
// byteArrayEquals with valueOf() 853971.0 ops/s 1.171000 us/op 9963051 runs 16.07 s
describe("root equals", () => {
setBenchOpts({maxMs: 60 * 1000, threshold: Infinity});
setBenchOpts({noThreshold: true});
const stateRoot = fromHexString("0x6c86ca3c4c6688cf189421b8a68bf2dbc91521609965e6f4e207d44347061fee");
const rootTree = ssz.Root.createTreeBackedFromStruct(stateRoot);

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {
ACTIVE_PRESET,
MAX_ATTESTATIONS,
@@ -68,8 +68,6 @@ import {StateBlock} from "../../types";
//
describe("phase0 processBlock", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
if (ACTIVE_PRESET !== PresetName.mainnet) {
throw Error(`ACTIVE_PRESET ${ACTIVE_PRESET} must be mainnet`);
}

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {allForks} from "../../../../src";
import {StateEpoch} from "../../types";
import {generatePerfTestCachedStatePhase0, perfStateId} from "../../util";
@@ -7,10 +7,9 @@ import {generatePerfTestCachedStatePhase0, perfStateId} from "../../util";
// network conditions. See also individual benchmarks for shuffling computations.
describe("phase0 afterProcessEpoch", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
itBench<StateEpoch, StateEpoch>({
id: `phase0 afterProcessEpoch - ${perfStateId}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
before: () => {
const state = generatePerfTestCachedStatePhase0({goBackOneSlot: true});
const epochProcess = allForks.beforeProcessEpoch(state);

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {allForks} from "../../../../src";
import {State} from "../../types";
import {generatePerfTestCachedStatePhase0, perfStateId} from "../../util";
@@ -9,10 +9,9 @@ import {generatePerfTestCachedStatePhase0, perfStateId} from "../../util";
// 3. Iterate over status to compute total balances. Cost = 'proportional' to $VALIDATOR_COUNT not network conditions
describe("phase0 beforeProcessEpoch", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
itBench<State, State>({
id: `phase0 beforeProcessEpoch - ${perfStateId}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
before: () =>
generatePerfTestCachedStatePhase0({goBackOneSlot: true}) as allForks.CachedBeaconState<allForks.BeaconState>,
beforeEach: (state) => state.clone(),

View File

@@ -10,7 +10,9 @@ const slot = computeStartSlotAtEpoch(epoch) - 1;
const stateId = `${network}_e${epoch}`;
describe(`phase0 processEpoch - ${stateId}`, () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
setBenchOpts({
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
});
const stateOg = beforeValue(async () => {
const state = await getNetworkCachedState(network, slot, 300_000);
@@ -32,7 +34,7 @@ describe(`phase0 processEpoch - ${stateId}`, () => {
// Only in local environment compute a full breakdown of the cost of each step
describe(`phase0 processEpoch steps - ${stateId}`, () => {
setBenchOpts({threshold: Infinity, minRuns: 10});
setBenchOpts({noThreshold: true});
benchmarkPhase0EpochSteps(stateOg, stateId);
});

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {ssz} from "@chainsafe/lodestar-types";
import {config} from "@chainsafe/lodestar-config/default";
import {allForks} from "../../../../src";
@@ -14,8 +14,6 @@ import {StateEpoch} from "../../types";
// statuses: All balances are low enough to trigger an effective balance change
describe("phase0 processEffectiveBalanceUpdates", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 5});
const vc = numValidators;
const testCases: {id: string; changeRatio: number}[] = [
// Normal (optimal) mainnet network conditions: No effectiveBalance is udpated
@@ -32,6 +30,8 @@ describe("phase0 processEffectiveBalanceUpdates", () => {
for (const {id, changeRatio} of testCases) {
itBench<StateEpoch, StateEpoch>({
id: `phase0 processEffectiveBalanceUpdates - ${vc} ${id}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
minRuns: 5, // Worst case is very slow
before: () => getEffectiveBalanceTestData(vc, changeRatio),
beforeEach: ({state, epochProcess}) => ({state: state.clone(), epochProcess}),
fn: ({state, epochProcess}) => allForks.processEffectiveBalanceUpdates(state, epochProcess),

View File

@@ -1,5 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {sleep} from "@chainsafe/lodestar-utils";
import {itBench} from "@dapplion/benchmark";
import {allForks} from "../../../../src";
import {beforeProcessEpoch} from "../../../../src/allForks";
import {generatePerfTestCachedStatePhase0, numValidators} from "../../util";
@@ -17,8 +16,6 @@ import {StateEpoch} from "../../types";
// - indicesToEject: 0
describe("phase0 processRegistryUpdates", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 5});
const vc = numValidators;
const testCases: {id: string; notTrack?: boolean; lengths: IndicesLengths}[] = [
// Normal (optimal) mainnet network conditions: No effectiveBalance is udpated
@@ -57,15 +54,14 @@ describe("phase0 processRegistryUpdates", () => {
for (const {id, notTrack, lengths} of testCases) {
itBench<StateEpoch, StateEpoch>({
id: `phase0 processRegistryUpdates - ${vc} ${id}`,
threshold: notTrack ? Infinity : undefined,
// WeakRef keeps a strong reference to its constructor value until the event loop ticks.
// Without this `sleep(0)` all the SubTree(s) created updating the validators registry
// won't be garabage collected causing an OOM crash. Tracking issue https://github.com/nodejs/node/issues/39902
yieldEventLoopAfterEach: true,
minRuns: 5, // Worst case is very slow
noThreshold: notTrack,
before: () => getRegistryUpdatesTestData(vc, lengths),
beforeEach: async ({state, epochProcess}) => {
// WeakRef keeps a strong reference to its constructor value until the event loop ticks.
// Without this `sleep(0)` all the SubTree(s) created updating the validators registry
// won't be garabage collected causing an OOM crash. Tracking issue https://github.com/nodejs/node/issues/39902
await sleep(0);
return {state: state.clone(), epochProcess};
},
beforeEach: async ({state, epochProcess}) => ({state: state.clone(), epochProcess}),
fn: ({state, epochProcess}) => allForks.processRegistryUpdates(state, epochProcess),
});
}

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {phase0} from "../../../../src";
import {generatePerfTestCachedStatePhase0, numValidators} from "../../util";
import {StatePhase0Epoch} from "../../types";
@@ -15,8 +15,6 @@ import {FlagFactors, generateBalanceDeltasEpochProcess} from "./util";
// - eligibleAttester: 98%
describe("phase0 getAttestationDeltas", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 10});
const vc = numValidators;
const testCases: {id: string; isInInactivityLeak: boolean; flagFactors: FlagFactors}[] = [
{
@@ -43,6 +41,7 @@ describe("phase0 getAttestationDeltas", () => {
for (const {id, isInInactivityLeak, flagFactors} of testCases) {
itBench<StatePhase0Epoch, StatePhase0Epoch>({
id: `phase0 getAttestationDeltas - ${vc} ${id}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
before: () => {
const state = generatePerfTestCachedStatePhase0({goBackOneSlot: true});
const epochProcess = generateBalanceDeltasEpochProcess(state, isInInactivityLeak, flagFactors);

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {allForks} from "../../../../src";
import {beforeProcessEpoch} from "../../../../src/allForks";
import {generatePerfTestCachedStatePhase0, numValidators} from "../../util";
@@ -11,8 +11,6 @@ import {StateEpoch} from "../../types";
// - On normal mainnet conditions indicesToSlash = 0
describe("phase0 processSlashings", () => {
setBenchOpts({maxMs: 60 * 1000, minRuns: 5});
const vc = numValidators;
const testCases: {id: string; indicesToSlashLen: number}[] = [
// Normal (optimal) mainnet network conditions: No slashings. Ignore this case since it does nothing
@@ -27,6 +25,8 @@ describe("phase0 processSlashings", () => {
for (const {id, indicesToSlashLen} of testCases) {
itBench<StateEpoch, StateEpoch>({
id: `phase0 processSlashings - ${vc} ${id}`,
yieldEventLoopAfterEach: true, // So SubTree(s)'s WeakRef can be garbage collected https://github.com/nodejs/node/issues/39902
minRuns: 5, // Worst case is very slow
before: () => getProcessSlashingsTestData(indicesToSlashLen),
beforeEach: ({state, epochProcess}) => ({state: state.clone(), epochProcess}),
fn: ({state, epochProcess}) => allForks.processRegistryUpdates(state, epochProcess),

View File

@@ -1,8 +1,6 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
describe.skip("shuffle number math ops", () => {
setBenchOpts({maxMs: 10 * 1000});
const forRuns = 100e5;
const j = forRuns / 2;

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {unshuffleList} from "../../../src";
// Lightouse Lodestar
@@ -7,8 +7,6 @@ import {unshuffleList} from "../../../src";
// 4000000 1.5617 s 4.9690 s (x3)
describe("shuffle list", () => {
setBenchOpts({maxMs: 30 * 1000});
// eslint-disable-next-line @typescript-eslint/naming-convention
const seed = new Uint8Array([42, 32]);

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {PointFormat} from "@chainsafe/bls";
import {
generatePerfTestCachedStatePhase0,
@@ -19,8 +19,6 @@ import {
// ✓ getPubkeys - persistent - req 1000 vs - 200000 vc 56593.10 ops/s 17.67000 us/op - 111477 runs 2.00 s
describe("api / impl / validator", () => {
setBenchOpts({maxMs: 10 * 1000});
let state: ReturnType<typeof generatePerfTestCachedStatePhase0>;
before(function () {
@@ -33,7 +31,7 @@ describe("api / impl / validator", () => {
for (const reqCount of reqCounts) {
itBench({
id: `getPubkeys - index2pubkey - req ${reqCount} vs - ${numValidators} vc`,
threshold: Infinity,
noThreshold: true,
fn: () => {
for (let i = 0; i < reqCount; i++) {
const pubkey = state.index2pubkey[i];
@@ -46,7 +44,7 @@ describe("api / impl / validator", () => {
for (const reqCount of reqCounts) {
itBench({
id: `getPubkeys - validatorsArr - req ${reqCount} vs - ${numValidators} vc`,
threshold: Infinity,
noThreshold: true,
fn: () => {
for (let i = 0; i < reqCount; i++) {
const validator = state.validators[i];
@@ -60,7 +58,7 @@ describe("api / impl / validator", () => {
itBench({
id: `getPubkeys - persistent - req ${reqCount} vs - ${numValidators} vc`,
// Only track regressions for 1000 in CI to ensure performance does not degrade
threshold: reqCount < 1000 ? Infinity : undefined,
noThreshold: reqCount < 1000,
fn: () => {
const validators = state.validators.persistent;
for (let i = 0; i < reqCount; i++) {

View File

@@ -1,10 +1,8 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {bls, PublicKey, SecretKey, Signature} from "@chainsafe/bls";
import {linspace} from "../../../src/util/numpy";
describe("BLS ops", function () {
setBenchOpts({maxMs: 60 * 1000});
type Keypair = {publicKey: PublicKey; secretKey: SecretKey};
type BlsSet = {publicKey: PublicKey; message: Uint8Array; signature: Signature};

View File

@@ -1,4 +1,4 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {expect} from "chai";
import {
allForks,
@@ -16,8 +16,6 @@ import {ssz} from "@chainsafe/lodestar-types";
// getAttestationsForBlock
// ✓ getAttestationsForBlock 4.410948 ops/s 226.7086 ms/op - 64 runs 51.8 s
describe("getAttestationsForBlock", () => {
setBenchOpts({maxMs: 60 * 1000});
let originalState: allForks.CachedBeaconState<allForks.BeaconState>;
before(function () {

View File

@@ -5,7 +5,7 @@ import {generateCachedState} from "../../../utils/state";
import {CheckpointStateCache} from "../../../../src/chain/stateCache";
describe("CheckpointStateCache perf tests", function () {
setBenchOpts({maxMs: 10 * 1000, threshold: Infinity});
setBenchOpts({noThreshold: true});
let state: CachedBeaconState<allForks.BeaconState>;
let checkpoint: phase0.Checkpoint;

View File

@@ -1,12 +1,10 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {ssz} from "@chainsafe/lodestar-types";
import {validateGossipAggregateAndProof} from "../../../../src/chain/validation";
import {generateTestCachedBeaconStateOnlyValidators} from "@chainsafe/lodestar-beacon-state-transition/test/perf/util";
import {getAggregateAndProofValidData} from "../../../utils/validationData/aggregateAndProof";
describe("validate gossip signedAggregateAndProof", () => {
setBenchOpts({maxMs: 60 * 1000});
const vc = 64;
const stateSlot = 100;

View File

@@ -1,12 +1,10 @@
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {itBench} from "@dapplion/benchmark";
import {ssz} from "@chainsafe/lodestar-types";
import {validateGossipAttestation} from "../../../../src/chain/validation";
import {generateTestCachedBeaconStateOnlyValidators} from "@chainsafe/lodestar-beacon-state-transition/test/perf/util";
import {getAttestationValidData} from "../../../utils/validationData/attestation";
describe("validate gossip attestation", () => {
setBenchOpts({maxMs: 60 * 1000});
const vc = 64;
const stateSlot = 100;

View File

@@ -521,10 +521,10 @@
enabled "2.0.x"
kuler "^2.0.0"
"@dapplion/benchmark@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@dapplion/benchmark/-/benchmark-0.2.0.tgz#0595ac6903e62be918bfc8fb6a557ecb0ded10d5"
integrity sha512-fPXqgCdV82uxqg1hxIYoXOSJHYaCOSDdf3AUMM33T21qGdBSjdGUbd4uXkw59Ec7rYNAuoahOTG9Albn9pLkRQ==
"@dapplion/benchmark@^0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@dapplion/benchmark/-/benchmark-0.2.2.tgz#cc9c78e5b8d2d04311bcf30cbc4c67783e2efc6f"
integrity sha512-1wkplmCOVo5U3vv6Vej9MkQ1KtWtTT7WIpwVKyZdNIPnLHG82X4JwySuaaXeAKwiMs0kQzE/+ax5gNwsfqqYpQ==
dependencies:
"@actions/cache" "^1.0.7"
"@actions/github" "^5.0.0"