Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve memory efficiency of seen cache #1073

Merged
merged 7 commits into from
May 1, 2024
Merged

Improve memory efficiency of seen cache #1073

merged 7 commits into from
May 1, 2024

Conversation

arnetheduck
Copy link
Contributor

The seen cache currently is a significant memory usage hotspot due to its inefficient implementation: for every entry, two copies of the message id + timing data + seq overhead causes it to use much more memory than it has to.

In addition, each check involves several layers of allocations as the computed message id gets salted.

This PR improves on the situation by:

  • using a hash of the message id with the salt instead of joining strings
  • computing the salted id only once per message
  • storing one digest instead of two message id:s

The `seen` cache currently is a significant memory usage hotspot due to
its inefficient implementation: for every entry, two copies of the
message id + timing data + `seq` overhead causes it to use much more
memory than it has to.

In addition, each check involves several layers of allocations as the
computed message id gets salted.

This PR improves on the situation by:

* using a hash of the message id with the salt instead of joining
strings
* computing the salted id only once per message
* storing one digest instead of two message id:s
@codecov-commenter
Copy link

codecov-commenter commented Mar 19, 2024

Codecov Report

Attention: Patch coverage is 88.70968% with 7 lines in your changes are missing coverage. Please review.

❗ No coverage uploaded for pull request base (master@2b53196). Click here to learn what that means.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1073   +/-   ##
=========================================
  Coverage          ?   84.53%           
=========================================
  Files             ?       91           
  Lines             ?    15517           
  Branches          ?        0           
=========================================
  Hits              ?    13118           
  Misses            ?     2399           
  Partials          ?        0           
Files Coverage Δ
libp2p/protocols/pubsub/floodsub.nim 88.18% <100.00%> (ø)
libp2p/protocols/pubsub/gossipsub.nim 86.46% <100.00%> (ø)
libp2p/protocols/pubsub/gossipsub/behavior.nim 88.83% <100.00%> (ø)
libp2p/protocols/pubsub/rpc/messages.nim 52.85% <ø> (ø)
libp2p/protocols/pubsub/timedcache.nim 82.89% <78.78%> (ø)

@arnetheduck
Copy link
Contributor Author

On holesky, this PR reduces memory usage of the seen cache by ~100mb

addedAt = previous.addedAt
let
previous = t.del(k) # Refresh existing item
addedAt = if previous.isSome():
Copy link
Contributor

@diegomrsantos diegomrsantos Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had a long PR in the past to remove this pattern from the codebase and decrease the risk of raising defects. You can use https://github.com/vacp2p/nim-libp2p/blob/unstable/libp2p/utility.nim#L125

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valueOr is not applicable in this case because we're accessing a field of previous[], not previous itself

Copy link
Contributor

@diegomrsantos diegomrsantos May 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but withValue can be used in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't work in generic code, due to similar problems as arnetheduck/nim-results#34

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to work fine:

    addedAt = block:
      previous.withValue(p):
        p[].addedAt
      else:
        now

Copy link
Contributor

@diegomrsantos diegomrsantos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@arnetheduck arnetheduck merged commit 02c96fc into master May 1, 2024
9 checks passed
@arnetheduck arnetheduck deleted the message-id-mem branch May 1, 2024 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: done
Development

Successfully merging this pull request may close these issues.

3 participants