Skip to content

Commit

Permalink
feat: track participants of produced aggregates (#5750)
Browse files Browse the repository at this point in the history
* Track participants of produced aggregates

* Add benchmark

* Fix typo in participants

---------

Co-authored-by: Nico Flaig <[email protected]>
  • Loading branch information
dapplion and nflaig authored Jul 14, 2023
1 parent 4b5280d commit de00b80
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 3 deletions.
8 changes: 8 additions & 0 deletions packages/beacon-node/src/api/impl/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ export function getValidatorApi({

const contribution = chain.syncCommitteeMessagePool.getContribution(subcommitteeIndex, slot, beaconBlockRoot);
if (!contribution) throw new ApiError(500, "No contribution available");

metrics?.production.producedSyncContributionParticipants.observe(
contribution.aggregationBits.getTrueBitIndexes().length
);

return {data: contribution};
},

Expand Down Expand Up @@ -538,6 +543,9 @@ export function getValidatorApi({

await waitForSlot(slot); // Must never request for a future slot > currentSlot

const aggregate = chain.attestationPool.getAggregate(slot, attestationDataRoot);
metrics?.production.producedAggregateParticipants.observe(aggregate.aggregationBits.getTrueBitIndexes().length);

return {
data: chain.attestationPool.getAggregate(slot, attestationDataRoot),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,11 @@ export async function produceBlockBody<T extends BlockType>(
const blockEpoch = computeEpochAtSlot(blockSlot);

if (blockEpoch >= this.config.ALTAIR_FORK_EPOCH) {
(blockBody as altair.BeaconBlockBody).syncAggregate = this.syncContributionAndProofPool.getAggregate(
parentSlot,
parentBlockRoot
const syncAggregate = this.syncContributionAndProofPool.getAggregate(parentSlot, parentBlockRoot);
this.metrics?.production.producedSyncAggregateParticipants.observe(
syncAggregate.syncCommitteeBits.getTrueBitIndexes().length
);
(blockBody as altair.BeaconBlockBody).syncAggregate = syncAggregate;
}

const fork = currentState.config.getForkName(blockSlot);
Expand Down
24 changes: 24 additions & 0 deletions packages/beacon-node/src/metrics/metrics/lodestar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,30 @@ export function createLodestarMetrics(
}),
},

production: {
producedAggregateParticipants: register.histogram({
name: "lodestar_produced_aggregate_participants",
help: "API impl produced aggregates histogram of participants",
// We care more about tracking low quality aggregates with low participation
// Max committee sizes are: 0.5e6 vc: 244, 1e6 vc: 488
buckets: [1, 5, 20, 50, 100, 200, 400],
}),
producedSyncContributionParticipants: register.histogram({
name: "lodestar_produced_sync_contribution_participants",
help: "API impl produced sync contribution histogram of participants",
// We care more about tracking low quality aggregates with low participation
// Max committee sizes fixed to 512/4 = 128
buckets: [1, 5, 20, 50, 128],
}),
producedSyncAggregateParticipants: register.histogram({
name: "lodestar_produced_sync_aggregate_participants",
help: "API impl produced sync aggregate histogram of participants",
// We care more about tracking low quality aggregates with low participation
// Max committee sizes fixed to 512
buckets: [1, 5, 20, 50, 100, 200, 512],
}),
},

// Beacon state transition metrics

epochTransitionTime: register.histogram({
Expand Down
13 changes: 13 additions & 0 deletions packages/beacon-node/test/perf/util/bitArray.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import crypto from "node:crypto";
import {itBench, setBenchOpts} from "@dapplion/benchmark";
import {BitArray} from "@chainsafe/ssz";
import {intersectUint8Arrays} from "../../../src/util/bitArray.js";
Expand Down Expand Up @@ -45,6 +46,18 @@ describe("Intersect BitArray vs Array+Set", () => {
}
});

describe("BitArray.trueBitCount", () => {
for (const bitLen of [128, 248, 512]) {
itBench({
id: `bitArray.getTrueBitIndexes() bitLen ${bitLen}`,
beforeEach: () => new BitArray(crypto.randomBytes(Math.ceil(bitLen / 8)), bitLen),
fn: (bitArray) => {
bitArray.getTrueBitIndexes().length;
},
});
}
});

function linspace(start: number, end: number, step: number): number[] {
const arr: number[] = [];
for (let i = start; i < end; i += step) {
Expand Down

0 comments on commit de00b80

Please sign in to comment.