Transfering array of C structs to main JS thread with zero-copy via SharedArrayBuffer #22007
Unanswered
badgermole
asked this question in
Q&A
Replies: 1 comment 9 replies
-
I think you the right track here in terms of using SAB to trasfrer your data. However, I would avoid using postMessage at all and instead start you application on the main thread. You will then already have access to the SAD on the main thread and you create a new pthread to do all your long running work. When the long-running work is done you can signal the main thread and it can retrieve the data from memory via your embind binding. This way you can use embind rather than trying to hard code the data layout of your objects. |
Beta Was this translation helpful? Give feedback.
9 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi all,
Executive Summary:
I am trying to accomplish a zero-copy transfer of an array of structured data from C++ up to the main JS thread.
Please see here for a diagram showing the basic runtime environment.
I would like to know if the method I'm attempting is plausible, or if there is a better way.
I know that Emscripten gives me a JS object representing my array of structs, and that it can correctly find the data for each element, via its JSRet.get(i) method. I'm hoping that I can do similarly using a DataView up in the main JS thread.
'Why':
I'm using Emscripten version 3.1.58.
Details:
Given the following C++ source:
I have a WebWorker, BasicTests.js that instantiates the WASM and calls its APIs. The worker will subsequently postMessage(results) to pass the results of the WASM API to the main thread(main.mjs).
Now, I can iterate via myStructVec.get(i) and see the elements and their values nicely.
My problem comes when I try
self.postMessage(myStructVec);
It seems the structured clone algorithm can't work with that object, and main.mjs receives an empty object, {}.
I know, however, that the WebAssembly.memory is a SharedArrayBuffer (SAB) and that I can tranfer that across without the cost of a copy. And I can see that the offset of myStructVec in the module instance HEAPU8 is given by:
const vecAddr = myStructVec.$$.ptr;
So my thought is to post vecAddr and the number of elements up to main.mjs, and there in the main thread, take advantage of the JS DataView to give me a proper MyStruct view on the SAB.
I have in fact had some success doing just that. However, I don't understand the layout of m_myStructVector in WASM memory. As a result, I get elements 0-9 okay, but then the pattern in memory gets wonky as far as the strings are concerned:
etc.
As far as I'm concerned this is a partial win as I've been able to show that I can transfer the SAB to main and look at it using a DataView.
Does this sound reasonable, and am I going about this correctly, just with misunderstanding the memory layout for structures such as this (especially ones with std::string)? Or is there a completely different 0-copy way I can go about this?
I figure the memory layout must be understandable since Emscripten implements a JS object.get(i) method that gives the correct values. Can I more-or-less copy that (where is that?)?
Thanks for comments or questions!
Beta Was this translation helpful? Give feedback.
All reactions