Skip to content

perf: preallocate slices on swarm and protocol hot paths#3524

Open
Sahil-4555 wants to merge 2 commits into
libp2p:masterfrom
Sahil-4555:perf/preallocate-hot-path-slices
Open

perf: preallocate slices on swarm and protocol hot paths#3524
Sahil-4555 wants to merge 2 commits into
libp2p:masterfrom
Sahil-4555:perf/preallocate-hot-path-slices

Conversation

@Sahil-4555

Copy link
Copy Markdown
Contributor

In reviewing some performance paths I observed that there are quite a few spots in our hot paths (dialling connections, filtering addresses, doing protocol negotiation, pushing identify messages, etc) where we declare slices as nil or with zero capacity and then continue to append to them in a loop.

Since we know the exact size or the max length of the collection up-front, Go is doing extra work under the hood. It allocates a backing array, and when the slice grows, it allocates another bigger one and copies all the data over. Then it leaves the old ones for GC to clean up.

So in this PR I've updated these places to preallocate the slices with the right capacity upfront.

What’s the benefit?

  1. Less GC workload: We allocate the same size once. Which means we don’t create a lot of little, short-lived arrays that the Garbage Collector has to go and clean up later. This will help with dial storms or boot up when there is a lot of traffic.
  2. CPU savings: We save CPU cycles by not copying elements from old arrays to new ones as slices grow.
  3. Slightly faster loops: For instance, in ConvertFromStrings in core/protocol/id.go, we now assign directly via index (res[i] = ...) rather than using append(), avoiding slice capacity checks.

What has changed ?

  • Swarm Dialling: Pre-allocated todial/tojoin in dial_worker.go with len(addrRanking) and did similar updates for resolution and filtering slices in swarm_dial.go and swarm.go.
    Dial Ranker: We saved the original address count prior to filtering so we can size the res delay slice correctly from the start.
  • Identify & Protocol Convert: Changed string to ID convertion to direct index assignment with preallocated slices. Preallocated protocol diff slices.
    Address book & Autorelay/Autonat: Preallocated slices in basic host’s diffAddrs, autonat’s skipPeer and autorelay’s cleanupAddressSet

Check

I have run all the test cases for the modified packages and all is fine. No behavioural change, just clean memory optimisation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant