Skip to content
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

Using trunk with wasm_thread #680

Open
Shapur1234 opened this issue Jan 20, 2024 · 9 comments
Open

Using trunk with wasm_thread #680

Shapur1234 opened this issue Jan 20, 2024 · 9 comments
Labels
help wanted Extra attention is needed investigate More investigation is needed

Comments

@Shapur1234
Copy link

I would like to use the wasm_thread library inside of a trunk project, but I was unable to create a functioning test application using the two.
I tried to splice together the trunk cdylib example with and example from the wasm_thread repo, but couldn't get it to work.

My latest attempt built successfully, when run, panics called Result::unwrap() on an Err value: JsValue(DataCloneError: WebAssembly. Memory object could not be cloned.
I am not very knowledgeable with trunk, but I have successfully used wasm_thread with wasm-pack in the past.

Are there any examples on how to use trunk with the wasm_thread library?

@ctron
Copy link
Collaborator

ctron commented Jan 22, 2024

Trunk is "just" a build tool for Rust based WebAssembly applications (for the browser). In general, I think that should work with wasm_thread. I might just be that the way other tools (like wasm_bindgen) get called might differ a bit from what wasm_thread expects.

Maybe people can easier help if there would be a reproducer for this.

@ctron ctron added help wanted Extra attention is needed investigate More investigation is needed labels Jan 22, 2024
@Shapur1234
Copy link
Author

Shapur1234 commented Jan 24, 2024

Thank you for you reply.
I've looked into this some more.

To compile wasm_thread, you need to enable some experimental flags and recompile the standard library with atomics enable.

Example from the wasm_thread example:

RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals'
cargo +nightly build --example simple --target wasm32-unknown-unknown --release -Z build-std=std,panic_abort

The problem is, I think the -Z build-std=std,panic_abort part. I haven't been able to pass that argument to trunk (something like trunk serve -- -Z build-std=std,panic_abort doesn't work.

Is it possible to recompile the standard library when building using trunk (passing the -Z build-std=std,panic_abort argument through trunk to cargo)?

P.S.: This repo contains my latest attempts at a minimal example (note: I am also trying to build this using nix crane)

@ctron
Copy link
Collaborator

ctron commented Jan 25, 2024

I don't think that's possible … yet!

It might make sense to add that using a data- attribute (data-z?). It's definitely for the "pro" user :)

@ctron
Copy link
Collaborator

ctron commented Jan 29, 2024

So according to the cargo documentation, you can already do this with cargo alone: https://doc.rust-lang.org/cargo/reference/unstable.html

Anything which can be configured with a -Z flag can also be set in the cargo config file (.cargo/config.toml) in the unstable table. For example:

[unstable]
mtime-on-use = true
build-std = ["core", "alloc"]

So, I am not sure there's anything for trunk to do TBH.

@ctron
Copy link
Collaborator

ctron commented Jan 29, 2024

Ok, I think I know what the problem is. Trunk creates the bootstrapper for the wasm initialization. And wasm_thread requires a specific entry point to be called:

      wasm_bindgen('./target/simple_bg.wasm').then((wasm) => {
        wasm.run();
      });

That's currently not happening. But I am sure we could add this.

@Shapur1234
Copy link
Author

Shapur1234 commented Jan 29, 2024

I have updated my minimal example test repo.

So according to the cargo documentation, you can already do this with cargo alone: https://doc.rust-lang.org/cargo/reference/unstable.html

I think I tried this before and it didn't work, so I tried it again... and it now works! 😵‍💫 (Or rather it compiles)

When I run the test application (using trunk serve):
error

Ok, I think I know what the problem is. Trunk creates the bootstrapper for the wasm initialization. And wasm_thread requires a specific entry point to be called:

The error seems to me to be exactly the issue you are describing.

That's currently not happening. But I am sure we could add this.

That would be great. I think being able to run multi-threaded code using "native std::threads" (not just standard webworkers) would be very useful.
(And not just for my use-case of this (a minecraft-like game )

@ctron
Copy link
Collaborator

ctron commented Jan 30, 2024

That would be great. I think being able to run multi-threaded code using "native std::threads" (not just standard webworkers) would be very useful.

However, the result will not be that. wasm_thread still uses web workers under the hood. It just tries to hide that fact away from you. And peeking into that code, I am wondering if it wouldn't be cleaner to just just acknowledge that fact and add some small abstraction layer in your application to deal with this. In the end, if it's running in a browser, it will always be single threaded.

@ctron
Copy link
Collaborator

ctron commented Jan 30, 2024

Ok, digging a bit more into this: It looks like it creates a new worker, and then tries to send over the "memory" of the original WASM module. Which feels kind of weird. And it looks like the browser actually prevents that. Things can be sent to other web workers, but not everything: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm

Sending the memory handle might work, but only when the WebAssembly memory was initialized as "shared": https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#shared_memories

There's another crate with a similar approach: https://github.com/RReverser/wasm-bindgen-rayon … however, it also requires a nightly compiler from 2022.

It seems to be around the flag of +atomics: rustwasm/wasm-bindgen#2225 (comment) … but honestly, I've no idea. Unfortunately, I don't have the time to dig deeper. If you have a working setup and some things that would help you get there, let me know and we might be able to add this to trunk.

@Shapur1234
Copy link
Author

Shapur1234 commented Jan 30, 2024

That would be great. I think being able to run multi-threaded code using "native std::threads" (not just standard webworkers) would be very useful.

However, the result will not be that. wasm_thread still uses web workers under the hood. It just tries to hide that fact away from you. And peeking into that code, I am wondering if it wouldn't be cleaner to just just acknowledge that fact and add some small abstraction layer in your application to deal with this. In the end, if it's running in a browser, it will always be single threaded.

For me, the main benefit of wasm_thread over plain webworkers is, that I can use the same code (threaded) for both wasm and native.

If you have a working setup and some things that would help you get there, let me know and we might be able to add this to trunk.

I'll try fiddling with it a bit more, if I get anywhere, I'll share my progress here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed investigate More investigation is needed
Projects
None yet
Development

No branches or pull requests

2 participants