Add shared memory regions and shared buffers over iommap - #73
Merged
Conversation
Bulk data between Erlang and Python contexts no longer has to cross the
socket: py_shm regions are files mapped MAP_SHARED on both sides (no copy
on the Erlang side, one copy when Erlang writes), usable as plain terms in
any context mode, and py_buffer:new(#{shared => true}) is a streaming
input buffer over such a region with ring backpressure, so wsgi.input
works in isolated contexts. iommap is an optional dependency. Read-only
handles keep a callee from writing into a region.
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
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.
Adds shared memory between Erlang and Python contexts, on top of iommap (an optional dependency).
Isolated contexts copy every argument and result through the socket, which is fine for terms and wrong for a 64 MB array. A
py_shmregion is a fixed-size file mappedMAP_SHAREDby both sides: Erlang reads it with no copy and writes it with one, Python sees it as a buffer (numpy.frombufferworks on it directly). The handle is a plain term, so it travels inside any argument or result, and the same wrappers serve embedded and isolated contexts, so a pool can mix modes.py_buffer:new(#{shared => true})builds the streaming input buffer (wsgi.input) on such a region, with a ring, backpressure on the writer, and reads that survive a child restart.Flow control and notifications reuse the existing callback path rather than a new protocol, which is what makes the mechanism mode-independent. Sharing keeps fault isolation intact; it does hand the callee the bytes of the region, so handles can be passed read-only and
py_shm:binary/3is documented as a live view. Sealing and syscall filtering are left for the security isolation work.Measured on macOS: 64 MB from Python to Erlang in 5.5 ms instead of 284 ms through the socket, 64 MB from Erlang to Python in 74 ms instead of 324 ms; below a couple of MB the socket stays cheaper. Validated on macOS and FreeBSD.