-
Notifications
You must be signed in to change notification settings - Fork 4.1k
feat(iavl): add Pin and UnsafeBytes design for managing mmaps #25657
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
Merged
+190
−44
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #25657 +/- ##
==========================================
- Coverage 70.42% 70.22% -0.21%
==========================================
Files 833 835 +2
Lines 54395 54414 +19
==========================================
- Hits 38310 38212 -98
- Misses 16085 16202 +117
🚀 New features to boost your workflow:
|
Contributor
|
@aaronc your pull request is missing a changelog! |
technicallyty
approved these changes
Dec 10, 2025
aljo242
approved these changes
Dec 10, 2025
warpbuild-benchmark-bot bot
added a commit
to WarpBuilds/cosmos-sdk
that referenced
this pull request
Dec 11, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Whenever we memory map a file we obtain a virtual memory address which becomes invalid when we unmap the file. Mapping and unmapping happen continously throughout the lifecycle of IAVLX changesets and if we reference an unmapped memory address there will be a system fault.
In order to allow for concurrent access to memory mapped files in IAVLX (a critical optimization), we use a reference counting system to make sure that the cleanup thread doesn't unmap files when the mapped memory is still in use.
In the original IAVLX implementation, this reference counting happened internally within the
Changesettype in every single getter method. This was pretty messy and verbose and I wouldn't want to subject anyone to reviewing that code the way it is. In addition, it was sub-optimal performance wise because we were forced to copy any transient memory buffers which increases allocation which increases pressure on the garbage collector.This redesign moves the responsibility for pinning and unpinning mapped memory out to the edges. While this does mean that there are a bunch of
defer pin.Unpincalls whenever we access a node, the pattern itself is simpler and more like opening and closing a file. Essentially, whenever you're acess aNodeyou should expect that you have file like access to it and must effectively "close" it, which is sort of the case if it is mapped to a file. At the edges, however, this allows us to directly access memory mapped buffers via theUnsafeBytesabstraction which should make it clear that if you want to retain a non-transient reference to this "memory" you must copy it. This means that in query, mutation and hashing code we can now do key comparison and hash accumulation without extra allocation.In memiavl, they had
HashandSafeHashmethods on theNodeinterface itself to account for this behavior, but the meaning wasn't very clear or obvious. I think assuming these bytes are unsafe to retain is a better starting point. Thus theUnsafeByteswrapper is used for returning bytes fromKey,ValueandHashmethods because these[]bytearrays may reference mmaps.