Skip to content

Commit a858aeb

Browse files
storage: avoid per-kv allocations during consistency checks
I noticed in an `alloc_objects` heap profile on a 3-node cluster restoring tpcc that more than 46% of all allocations were made in `computeChecksumPostApply`. Specifically, these allocations were all made in `Replica.sha512`. 28% of allocations were due to protobuf marshaling of `hlc.LegacyTimestamp`. The other 18% was in `encoding/binary.Write`. This removes both of these sources of per-key allocations. The first allocation was avoided by sharing a byte buffer across protobuf marshals. The second was avoided by removing the call to `binary.Write` (see golang/go#27403). I confirmed that this is no longer an issue by looking at heap profiles from before and after in a test that performed a consistency check. I plan to follow up on golang/go#27403 and search for any other offenders in our codebase. I already see a few. Release note: None
1 parent 9f1a5b5 commit a858aeb

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

pkg/storage/replica_consistency.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,11 @@ func (r *Replica) sha512(
360360
defer iter.Close()
361361

362362
var alloc bufalloc.ByteAllocator
363+
var intBuf [8]byte
364+
var legacyTimestamp hlc.LegacyTimestamp
365+
var timestampBuf []byte
363366
hasher := sha512.New()
364367

365-
var legacyTimestamp hlc.LegacyTimestamp
366368
visitor := func(unsafeKey engine.MVCCKey, unsafeValue []byte) error {
367369
if snapshot != nil {
368370
// Add (a copy of) the kv pair into the debug message.
@@ -375,24 +377,30 @@ func (r *Replica) sha512(
375377
}
376378

377379
// Encode the length of the key and value.
378-
if err := binary.Write(hasher, binary.LittleEndian, int64(len(unsafeKey.Key))); err != nil {
380+
binary.LittleEndian.PutUint64(intBuf[:], uint64(len(unsafeKey.Key)))
381+
if _, err := hasher.Write(intBuf[:]); err != nil {
379382
return err
380383
}
381-
if err := binary.Write(hasher, binary.LittleEndian, int64(len(unsafeValue))); err != nil {
384+
binary.LittleEndian.PutUint64(intBuf[:], uint64(len(unsafeValue)))
385+
if _, err := hasher.Write(intBuf[:]); err != nil {
382386
return err
383387
}
384388
if _, err := hasher.Write(unsafeKey.Key); err != nil {
385389
return err
386390
}
387391
legacyTimestamp = hlc.LegacyTimestamp(unsafeKey.Timestamp)
388-
timestamp, err := protoutil.Marshal(&legacyTimestamp)
389-
if err != nil {
392+
if size := legacyTimestamp.Size(); size > cap(timestampBuf) {
393+
timestampBuf = make([]byte, size)
394+
} else {
395+
timestampBuf = timestampBuf[:size]
396+
}
397+
if _, err := protoutil.MarshalToWithoutFuzzing(&legacyTimestamp, timestampBuf); err != nil {
390398
return err
391399
}
392-
if _, err := hasher.Write(timestamp); err != nil {
400+
if _, err := hasher.Write(timestampBuf); err != nil {
393401
return err
394402
}
395-
_, err = hasher.Write(unsafeValue)
403+
_, err := hasher.Write(unsafeValue)
396404
return err
397405
}
398406

0 commit comments

Comments
 (0)