Skip to content

Commit

Permalink
Improve slasher cold boot duration.
Browse files Browse the repository at this point in the history
Before this commit, on a slasher cold boot (aka, without any db),
the `updatedChunkByChunkIndex` function looped for all validators
AND for all epochs between the genesis epoch and the current epoch.

This could take several dozen of minutes, and it is useless since the
min/max spans are actually a circular buffer with a limited lenght.
Cells of min/max spans can be overwritten (with the same value)
plenty of times.

After this commit, the `updatedChunkByChunkIndex` function loops
for all validators AND AT most 'historyLength' lenght.
Every cell of min/max spans are written AT MOST once.

Time needed for slasher boot goes from `O(nm)` to "only" `O(m)`, where:
- `n` is the number of epochs since the genesis.
- `m` is the number of validators.
  • Loading branch information
nalepae committed Feb 16, 2024
1 parent 112ab9a commit f559e63
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
14 changes: 11 additions & 3 deletions beacon-chain/slasher/detect_attestations.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,6 @@ func (s *Service) updatedChunkByChunkIndex(
currentEpoch primitives.Epoch,
validatorChunkIndex uint64,
) (map[uint64]Chunker, error) {
var err error

chunkByChunkIndex := map[uint64]Chunker{}

validatorIndexes := s.params.validatorIndexesInChunk(validatorChunkIndex)
Expand All @@ -257,11 +255,21 @@ func (s *Service) updatedChunkByChunkIndex(
latestEpochWritten, ok := s.latestEpochWrittenForValidator[validatorIndex]

// Start from the epoch just after the latest epoch written.
epochToWrite := latestEpochWritten + 1
epochToWrite, err := latestEpochWritten.SafeAdd(1)
if err != nil {
return nil, errors.Wrap(err, "could not add 1 to latest epoch written")
}

if !ok {
epochToWrite = 0
}

// It is useless to update more than `historyLength` epochs, since
// the chunks are circular and we will be overwritten at least one.
if currentEpoch-epochToWrite >= s.params.historyLength {
epochToWrite = currentEpoch + 1 - s.params.historyLength
}

for epochToWrite <= currentEpoch {
// Get the chunk index for the latest epoch written.
chunkIndex := s.params.chunkIndex(epochToWrite)
Expand Down
33 changes: 33 additions & 0 deletions beacon-chain/slasher/detect_attestations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,39 @@ func Test_epochUpdateForValidators(t *testing.T) {
0: {neutralMax, neutralMax, neutralMax, 55, neutralMax, neutralMax, neutralMax, 55},
},
},
{
name: "start with some data - high latest updated epoch",
chunkSize: 4,
validatorChunkSize: 2,
historyLength: 12,
currentEpoch: 16,
validatorChunkIndex: 21,
latestUpdatedEpochByValidatorIndex: map[primitives.ValidatorIndex]primitives.Epoch{42: 2, 43: 3},
initialMinChunkByChunkIndex: map[uint64][]uint16{
// | validator 42 | validator 43 |
0: {55, 55, 55, 55, 55, 55, 55, 55},
1: {66, 66, 66, 66, 66, 66, 66, 66},
2: {77, 77, 77, 77, 77, 77, 77, 77},
},
expectedMinChunkByChunkIndex: map[uint64][]uint16{
// | validator 42 | validator 43 |
0: {neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin},
1: {neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin},
2: {neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin, neutralMin},
},
initialMaxChunkByChunkIndex: map[uint64][]uint16{
// | validator 42 | validator 43 |
0: {55, 55, 55, 55, 55, 55, 55, 55},
1: {66, 66, 66, 66, 66, 66, 66, 66},
2: {77, 77, 77, 77, 77, 77, 77, 77},
},
expectedMaxChunkByChunkIndex: map[uint64][]uint16{
// | validator 42 | validator 43 |
0: {neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax},
1: {neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax},
2: {neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax, neutralMax},
},
},
}

for _, tt := range testCases {
Expand Down

0 comments on commit f559e63

Please sign in to comment.