Skip to content

Commit

Permalink
Free dedupe buffer's tracking map after shrink
Browse files Browse the repository at this point in the history
Go doesn't free map blocks, even after a map shrinks
considerably. The dedupe buffer tends to store a lot of
keys for a start-of-day snapshot, make sure we clean
up the leaked map capacity once we're back down to
zero.

Upstream issue: golang/go#20135
  • Loading branch information
fasaxc committed Nov 25, 2024
1 parent 2ea7981 commit 442fe0f
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions libcalico-go/lib/backend/syncersv1/dedupebuffer/dedupe_buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type DedupeBuffer struct {
// keyToPendingUpdate holds an entry for each updateWithStringKey in the
// pendingUpdates queue
keyToPendingUpdate map[string]*list.Element
peakPendingUpdatesLen int

// liveResourceKeys Contains an entry for every key that we have sent to
// the consumer and that we have not subsequently sent a deletion for.
liveResourceKeys set.Set[string]
Expand Down Expand Up @@ -176,6 +178,7 @@ func (d *DedupeBuffer) OnUpdatesKeysKnown(updates []api.Update, keys []string) {
update: u,
})
d.keyToPendingUpdate[key] = element
d.peakPendingUpdatesLen = max(len(d.keyToPendingUpdate), d.peakPendingUpdatesLen)
}
}
queueNowEmpty := d.pendingUpdates.Len() == 0
Expand Down Expand Up @@ -252,6 +255,14 @@ func (d *DedupeBuffer) pullNextBatch(buf []any, batchSize int) []any {
if u, ok := first.Value.(updateWithStringKey); ok {
key := u.key
delete(d.keyToPendingUpdate, key)
if len(d.keyToPendingUpdate) == 0 && d.peakPendingUpdatesLen > 100 {
// Map blocks never get freed when a map is scaled down.
// https://github.com/golang/go/issues/20135
// Opportunistically free the map when it's empty. This can
// free a good amount of RAM after loading a large snapshot.
d.keyToPendingUpdate = map[string]*list.Element{}
d.peakPendingUpdatesLen = 0
}
// Update liveResourceKeys now, before we drop the lock. Once we drop
// the lock we're committed to sending these keys.
if u.update.Value == nil {
Expand Down

0 comments on commit 442fe0f

Please sign in to comment.