Dear fellow embedded enthusiasts,
when we internally talked about adding zero-copy IPC to WIT (shared memory) by supporting a iceoryx2 like API we found that just returning a borrow<list<u8>>
from a subscription resource (or a borrow-mut<list<u8>>
from a publisher resource) won't cover all of our needs.
Instead at some point in time we also want to support a borrow<list<list<string>>>
as well. But non-constant-size/bounded lists need a heap allocation which clashes with shared memory placement. You probably want to design a new ABI :scream: for in-place creation and access of list
and string
objects, like flatbuf, protobuf, capn-proto or similar.
This would be similar to multi-memory support as the addresses in string/vector ABI would be relative to the mounting point of the shared memory. (These addresses could also independently choose between 8, 16, 32, or 64 bit size as long as both side agree).
I just realized (or was told) that this also can be used to serialize WIT based messages for network protocols, on disk storage, using pre-allocated memory pools for calls (functional safety) and similar.
Do you want me to prepare a presentation on this for tomorrow's meeting?
Of course these data types have been a hot topic for years, see Stroustrup's Flats and Boost interprocess for C++ centered solutions.
Also there is e.g. https://crates.io/crates/flatty for Rust.
Sorry, the link above links to the old iceoryx Rust implementation, the new one is at https://github.com/eclipse-iceoryx/iceoryx2/tree/main?tab=readme-ov-file#publish-subscribe - as the old iceoryx already published v2.0.6 I regularly confuse them.
Hey Christoph, I've been out of the office, that would be a great topic. I think there is a lot of interest.
Today's presentation about binary representation of nested WIT types in shared memory
Allocation-pools-Shared-memory-in-WIT.pptx
Update: I was able to sketch a potential syntax in WIT for shared memory optimized types, see https://github.com/WebAssembly/component-model/issues/398 for details
@Christof Petig . Wondering if we consider the ABI of the element size of a list with fixed length, it's already presented in a flat form in memory. So, what's the difference between a 'flat data representation' and a 'list with a fixed length'
def elem_size_list(elem_type, maybe_length):
if maybe_length is not None:
return maybe_length * elem_size(elem_type)
return 8
There is no fixed length string variant. I proposed bounded lists and strings in a component model issue but always had doubts that it might waste memory compared to allocating from a pool (this one).
This one would be the first proposal I am aware of that could modify the existing ABI to make calls zero copy over shared memory.
And compared to bounded lists I initially shied back from the complexity of flat types, but found that is moderate once I fully defined it.
Was last week's presentation recorded? I hoped to watch it after the fact but it hasn't been released just yet on the Bytecode Alliance youtube channel.
Yes, it was recorded. But the recording isn't publicly available yet, as far as I know.
@Christof Petig Got a following questions on "multi-memory" which you mentioned in issue #398.
If I understand correctly, multi-memory is the foundation of the zero-copy solution. I assume this solution is aimed at real-world applications rather than just a theoretical experiment. You must be aware of the challenges with toolchain support for multi-memory. The question is, how do you plan to deal with the lack of toolchain? Will there be a workaround to ease the situation?
My best strategy for now is to map multi memory into the flat address space. This is known to work on POSIX where the mmap call enables shared memory with all existing languages.
Reserving that storage requires either linker script magic (or shared library like runtime relocation) to reserve memory below the start of linear memory or a special (read host runtime) call to grow linear memory reserved for and mapped to a different multi memory area.
As you can see neither is real multi memory as I don't think there is a good way of mapping it to a contemporary C inspired language. 35 years ago we had segmented memory models but everyone was happy to see them gone. Probably CHERI with its pointer provenance can bring us a step in that direction, but the compile time fixed memory index is very alien to C pointer concepts.
Christof Petig said:
My best strategy for now is to map multi memory into the flat address space. This is known to work on POSIX where the mmap call enables shared memory with all existing languages.
I'm not sure if you've seen the shared memory work thats come out from WAMR, it's currently in a PR, and is work from Midokura and Intel.
Seperately I know others have been exploring with mapping mmap directly into WAMR .
Chris Woods said:
I'm not sure if you've seen the shared memory work thats come out from WAMR, it's currently in a PR, and is work from Midokura and Intel.
Seperately I know others have been exploring with mapping mmap directly into WAMR .
Thank you, Chris, for bringing us together. I heard of the WAMR efforts and I believe the major difference is that I am striving for full isolation by only handing out single write access exclusive or shared read access to one out of many memory regions.
Because I want to convince that shared memory is not weakening the security principles while enabling zero copy deep types (using flat representations).
So my target is more a quick proof of concept in wasmtime and then the main target for us is native execution with zero copy and zero runtime allocation (functional safety), including streams and async calls in the WASI 0.3 style. All this with the future option to switch to wasm components by just changing the compilation target.
Last updated: Dec 23 2024 at 13:07 UTC