mirror of
https://github.com/ChainSafe/lodestar.git
synced 2026-01-09 15:48:08 -05:00
refactor: optimize event listener count checks (#8293)
## Summary This PR optimizes event listener count checks for `routes.events.EventType` emissions, following the principle that **listener count checks should only be added where there's expensive preprocessing work before emit**, since `emit()` is already a no-op when no listeners exist. ## Changes Made ### ✅ Added listener count checks (where expensive preprocessing occurs): **`packages/beacon-node/src/network/processor/gossipHandlers.ts`:** - **`dataColumnSidecar`** emission: Added check to avoid `kzgCommitments.map(toHex)` array mapping when no listeners **`packages/beacon-node/src/chain/prepareNextSlot.ts`:** - **`payloadAttributes`** emission: Added check to avoid `await getPayloadAttributesForSSE()` async function call when no listeners ### ✅ Removed unnecessary listener count checks (where no expensive preprocessing occurs): **`packages/beacon-node/src/network/processor/gossipHandlers.ts`:** - **`blockGossip`** emission: Removed check since it only uses existing variables `{slot, block: blockRootHex}` **`packages/beacon-node/src/api/impl/beacon/blocks/index.ts`:** - **`blockGossip`** emission: Removed check since it's a simple emission with existing variables ### ✅ Kept existing correct checks (for expensive operations): - **`blobSidecar`** emissions: Keep checks for `toHex()` conversions and `kzgCommitmentToVersionedHash()` - **All loop-based emissions** in `importBlock.ts`: Keep checks for `for` loop iterations - **`block`** emission: Keep check for `isOptimisticBlock()` computation ## Performance Benefits 1. **Reduced CPU usage**: Expensive operations like async function calls and array mapping only occur when needed 2. **Better resource utilization**: Memory allocations and computations are avoided when events won't be consumed 3. **Cleaner code**: Removed redundant checks where the emit operation itself is lightweight ## Key Principle Applied **Only add listener count checks where there's expensive preprocessing work before emission:** - ✅ Function calls, array operations, crypto operations - ❌ Simple emissions using existing variables Since `emit()` is already a no-op when no listeners exist, explicit checks are only beneficial when avoiding preprocessing overhead. ## Testing - ✅ Type checks pass - ✅ Build succeeds - ✅ Linting passes Resolves #7996 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -308,9 +308,7 @@ export function getBeaconBlockApi({
|
||||
}
|
||||
}
|
||||
|
||||
if (chain.emitter.listenerCount(routes.events.EventType.blockGossip)) {
|
||||
chain.emitter.emit(routes.events.EventType.blockGossip, {slot, block: blockRoot});
|
||||
}
|
||||
chain.emitter.emit(routes.events.EventType.blockGossip, {slot, block: blockRoot});
|
||||
|
||||
if (blockForImport.type === BlockInputType.availableData) {
|
||||
if (isForkPostFulu(blockForImport.blockData.fork)) {
|
||||
|
||||
@@ -191,7 +191,10 @@ export class PrepareNextSlotScheduler {
|
||||
this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
|
||||
|
||||
// If emitPayloadAttributes is true emit a SSE payloadAttributes event
|
||||
if (this.chain.opts.emitPayloadAttributes === true) {
|
||||
if (
|
||||
this.chain.opts.emitPayloadAttributes === true &&
|
||||
this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
|
||||
) {
|
||||
const data = await getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
|
||||
prepareState: updatedPrepareState,
|
||||
prepareSlot,
|
||||
|
||||
@@ -176,9 +176,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
||||
|
||||
logger.debug("Validated gossip block", {...logCtx, recvToValidation, validationTime});
|
||||
|
||||
if (chain.emitter.listenerCount(routes.events.EventType.blockGossip)) {
|
||||
chain.emitter.emit(routes.events.EventType.blockGossip, {slot, block: blockRootHex});
|
||||
}
|
||||
chain.emitter.emit(routes.events.EventType.blockGossip, {slot, block: blockRootHex});
|
||||
|
||||
return blockInput;
|
||||
} catch (e) {
|
||||
@@ -311,12 +309,14 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
||||
metrics?.gossipBlob.recvToValidation.observe(recvToValidation);
|
||||
metrics?.gossipBlob.validationTime.observe(validationTime);
|
||||
|
||||
chain.emitter.emit(routes.events.EventType.dataColumnSidecar, {
|
||||
blockRoot: blockRootHex,
|
||||
slot,
|
||||
index: dataColumnSidecar.index,
|
||||
kzgCommitments: dataColumnSidecar.kzgCommitments.map(toHex),
|
||||
});
|
||||
if (chain.emitter.listenerCount(routes.events.EventType.dataColumnSidecar)) {
|
||||
chain.emitter.emit(routes.events.EventType.dataColumnSidecar, {
|
||||
blockRoot: blockRootHex,
|
||||
slot,
|
||||
index: dataColumnSidecar.index,
|
||||
kzgCommitments: dataColumnSidecar.kzgCommitments.map(toHex),
|
||||
});
|
||||
}
|
||||
|
||||
logger.debug("Received gossip dataColumn", {
|
||||
slot: slot,
|
||||
|
||||
Reference in New Issue
Block a user