-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Option for host managed memory #1400
Conversation
Subscribe to Label ActionThis issue or pull request has been labeled: "wasmtime:api" Users Subscribed to "wasmtime:api"To subscribe or unsubscribe from this label, edit the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this! From an API perspective I think that this is an unfortunately tricky addition from the wasmtime
crate. In addition to some of the comments I've made below I think it'd also be good to have something like Memory::new_custom
or basically something where you can construct a Memory
with a custom allocator and then pass that around to mirror the functionality here as well.
Thanks for the comments! As you pointed out Allocator is a too general term. I'll be calling it MemoryCreator here. As for the safety concerns and possible things that can go wrong. The second entity is the MemoryCreator. This one should be thread safe (Sync). It could just call an mmap, or it could provide the memory from some preallocated pool. The memory creator should conform with MemoryPlan. If it can't it should fail. The biggest problem here is that if MemoryPlan struct changes (gets a new field), the maintainers of a custom MemoryCreator may fail to notice that. Currently MemoryPlan is quite a rich struct. Maybe it's a good idea to reorganize it? In particular memory limits and offset_guard_size are the fields which seem like good candidates to be passed to the custom allocator. As for MemoryStyle it seems to me like this is more like wasmtime's internal parameter used by wasmtime's MemoryCreator. The Memory::shared flag worries me most, but it doesn't seem to be used at all... Or we could just pass the required parameters explicitly and not through this struct.
Can you elaborate a bit more on that? I'm not sure I understand. Isn't MemoryCreator::new_memory() basically doing that? |
Sounds reasonable to me!
What you wrote down sounds good to me, thanks for writing that up! You're right yeah that the
This is where I think if we could define an API in the
A right yeah, I'm thinking of (Ideally if we could get away with only updating |
I created appropriate traits in the API. I ended up not adding Memory::new_custom thing. I don't really have a clear picture in my mind of how this should work. Maybe I'm misunderstanding something after all. The problem here is, that we want to be able to capture all memories created by "create_memories" from runtime, and current Memory interface allows to create only one. I guess, if that is what you would like to have there, I can add it like that. Let me know. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me, thanks for this!
Could this also add a few tests to crates/api/tests/*
which exercise usage of this?
crates/api/src/trampoline/memory.rs
Outdated
@@ -31,3 +37,41 @@ pub fn create_handle_with_memory(store: &Store, memory: &MemoryType) -> Result<I | |||
Box::new(()), | |||
) | |||
} | |||
|
|||
struct LinearMemoryProxy { | |||
mem: RefCell<Box<dyn LinearMemory>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come this is wrapped in a RefCell
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is complementary to:
wasmtime/crates/runtime/src/memory.rs
Line 147 in a325b62
let mut mmap = self.mmap.borrow_mut(); |
Basically it's here because RuntimeLinearMemory::vmmemory() takes &self and not &mut self, but needs to return mut ptr.
I added an example test and updated the rest according to the suggestions. Btw, maybe it's a good idea to make LinearMemory::grow() mutable? (Same for actual grow in wasmtime_runtime) Also I wrapped the whole test I added in not_for_windows module. Is there a better way to exclude this test from windows e.g. on the Cargo.toml level? |
Looking good! I think we'll want to remove |
Done. Also added a test for grow. |
Thanks! |
As per discussion on host managed memory on zulip started by @lostman here is a simple implementation.
To make things least invasive I ended up with two traits - one for allocator and one for actual memory. This way LinearMemory is not forced to know anything about the allocator and consequently does not need to inherit restrictions placed on the allocator (e.g. Sync).
Additionally DefaultAllocator is made public, so it's possible to create a wrapper around the existing allocator/memory (insert some hooks) and supply it as a custom one.
There are no specific test cases for custom allocators. Can be added if required.
Implementation itself is tested within existing tests with DefaultAllocator.
@alexcrichton @tschneidereit @peterhuene please have a look