Skip to content

Commit e86e816

Browse files
authored
fix: prune checkpoint states at syncing time (#7241)
* fix: prune checkpoint states at syncing time * fix: lint * fix: check-types in test
1 parent 18f4218 commit e86e816

File tree

3 files changed

+9
-37
lines changed

3 files changed

+9
-37
lines changed

packages/beacon-node/src/chain/chain.ts

-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ export class BeaconChain implements IBeaconChain {
293293
metrics,
294294
logger,
295295
clock,
296-
shufflingCache: this.shufflingCache,
297296
blockStateCache,
298297
bufferPool: this.bufferPool,
299298
datastore: fileDataStore

packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts

+3-24
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,20 @@ import {AllocSource, BufferPool, BufferWithKey} from "../../util/bufferPool.js";
99
import {IClock} from "../../util/clock.js";
1010
import {StateCloneOpts} from "../regen/interface.js";
1111
import {serializeState} from "../serializeState.js";
12-
import {ShufflingCache} from "../shufflingCache.js";
1312
import {CPStateDatastore, DatastoreKey, datastoreKeyToCheckpoint} from "./datastore/index.js";
1413
import {MapTracker} from "./mapMetrics.js";
1514
import {BlockStateCache, CacheItemType, CheckpointHex, CheckpointStateCache} from "./types.js";
1615

1716
export type PersistentCheckpointStateCacheOpts = {
1817
/** Keep max n states in memory, persist the rest to disk */
1918
maxCPStateEpochsInMemory?: number;
20-
/** for testing only */
21-
processLateBlock?: boolean;
2219
};
2320

2421
type PersistentCheckpointStateCacheModules = {
2522
metrics?: Metrics | null;
2623
logger: Logger;
2724
clock?: IClock | null;
2825
signal?: AbortSignal;
29-
shufflingCache: ShufflingCache;
3026
datastore: CPStateDatastore;
3127
blockStateCache: BlockStateCache;
3228
bufferPool?: BufferPool | null;
@@ -102,24 +98,12 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
10298
private preComputedCheckpoint: string | null = null;
10399
private preComputedCheckpointHits: number | null = null;
104100
private readonly maxEpochsInMemory: number;
105-
// only for testing, default false for production
106-
private readonly processLateBlock: boolean;
107101
private readonly datastore: CPStateDatastore;
108-
private readonly shufflingCache: ShufflingCache;
109102
private readonly blockStateCache: BlockStateCache;
110103
private readonly bufferPool?: BufferPool | null;
111104

112105
constructor(
113-
{
114-
metrics,
115-
logger,
116-
clock,
117-
signal,
118-
shufflingCache,
119-
datastore,
120-
blockStateCache,
121-
bufferPool,
122-
}: PersistentCheckpointStateCacheModules,
106+
{metrics, logger, clock, signal, datastore, blockStateCache, bufferPool}: PersistentCheckpointStateCacheModules,
123107
opts: PersistentCheckpointStateCacheOpts
124108
) {
125109
this.cache = new MapTracker(metrics?.cpStateCache);
@@ -153,10 +137,8 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
153137
throw new Error("maxEpochsInMemory must be >= 0");
154138
}
155139
this.maxEpochsInMemory = opts.maxCPStateEpochsInMemory ?? DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY;
156-
this.processLateBlock = opts.processLateBlock ?? false;
157140
// Specify different datastore for testing
158141
this.datastore = datastore;
159-
this.shufflingCache = shufflingCache;
160142
this.blockStateCache = blockStateCache;
161143
this.bufferPool = bufferPool;
162144
}
@@ -487,12 +469,9 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
487469
// 2/3 of slot is the most free time of every slot, take that chance to persist checkpoint states
488470
// normally it should only persist checkpoint states at 2/3 of slot 0 of epoch
489471
await sleep(secToTwoThirdsSlot * 1000, this.signal);
490-
} else if (!this.processLateBlock) {
491-
// normally the block persist happens at 2/3 of slot 0 of epoch, if it's already late then just skip to allow other tasks to run
492-
// there are plenty of chances in the same epoch to persist checkpoint states, also if block is late it could be reorged
493-
this.logger.verbose("Skip persist checkpoint states", {blockSlot, root: blockRootHex});
494-
return 0;
495472
}
473+
// at syncing time, it's critical to persist checkpoint states as soon as possible to avoid OOM during unfinality time
474+
// if node is synced this is not a hot time because block comes late, we'll likely miss attestation already, or the block is orphaned
496475

497476
const persistEpochs = sortedEpochs.slice(0, sortedEpochs.length - this.maxEpochsInMemory);
498477
for (const lowestEpoch of persistEpochs) {

packages/beacon-node/test/unit/chain/stateCache/persistentCheckpointsCache.test.ts

+6-12
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,9 @@ describe("PersistentCheckpointStateCache", () => {
9090
{
9191
datastore,
9292
logger: testLogger(),
93-
shufflingCache: new ShufflingCache(),
9493
blockStateCache: new FIFOBlockStateCache({}, {}),
9594
},
96-
{maxCPStateEpochsInMemory: 2, processLateBlock: true}
95+
{maxCPStateEpochsInMemory: 2}
9796
);
9897
cache.add(cp0a, states["cp0a"]);
9998
cache.add(cp0b, states["cp0b"]);
@@ -165,10 +164,9 @@ describe("PersistentCheckpointStateCache", () => {
165164
{
166165
datastore,
167166
logger: testLogger(),
168-
shufflingCache: new ShufflingCache(),
169167
blockStateCache: new FIFOBlockStateCache({}, {}),
170168
},
171-
{maxCPStateEpochsInMemory: 2, processLateBlock: true}
169+
{maxCPStateEpochsInMemory: 2}
172170
);
173171
cache.add(cp0a, states["cp0a"]);
174172
cache.add(cp0b, states["cp0b"]);
@@ -242,10 +240,9 @@ describe("PersistentCheckpointStateCache", () => {
242240
{
243241
datastore,
244242
logger: testLogger(),
245-
shufflingCache: new ShufflingCache(),
246243
blockStateCache: new FIFOBlockStateCache({}, {}),
247244
},
248-
{maxCPStateEpochsInMemory: 2, processLateBlock: true}
245+
{maxCPStateEpochsInMemory: 2}
249246
);
250247
cache.add(cp0a, states["cp0a"]);
251248
cache.add(cp0b, states["cp0b"]);
@@ -548,10 +545,9 @@ describe("PersistentCheckpointStateCache", () => {
548545
{
549546
datastore,
550547
logger: testLogger(),
551-
shufflingCache: new ShufflingCache(),
552548
blockStateCache: new FIFOBlockStateCache({}, {}),
553549
},
554-
{maxCPStateEpochsInMemory: 1, processLateBlock: true}
550+
{maxCPStateEpochsInMemory: 1}
555551
);
556552
cache.add(cp0a, states["cp0a"]);
557553
cache.add(cp0b, states["cp0b"]);
@@ -820,10 +816,9 @@ describe("PersistentCheckpointStateCache", () => {
820816
{
821817
datastore,
822818
logger: testLogger(),
823-
shufflingCache: new ShufflingCache(),
824819
blockStateCache: new FIFOBlockStateCache({}, {}),
825820
},
826-
{maxCPStateEpochsInMemory: 0, processLateBlock: true}
821+
{maxCPStateEpochsInMemory: 0}
827822
);
828823
cache.add(cp0a, states["cp0a"]);
829824
cache.add(cp0b, states["cp0b"]);
@@ -911,10 +906,9 @@ describe("PersistentCheckpointStateCache", () => {
911906
{
912907
datastore,
913908
logger: testLogger(),
914-
shufflingCache: new ShufflingCache(),
915909
blockStateCache: new FIFOBlockStateCache({}, {}),
916910
},
917-
{maxCPStateEpochsInMemory: 0, processLateBlock: true}
911+
{maxCPStateEpochsInMemory: 0}
918912
);
919913

920914
const root1a = Buffer.alloc(32, 100);

0 commit comments

Comments
 (0)