If most of the wasm modules spend a lot of time waiting on requests to other actors/providers/etc., then you could spawn much more executors then num cpu-cores, since most would be blocked either waiting for a request or blocked waiting for a reply from another actor/provider.
Actix update code#
You would spawn X instances of the executor and that would be the maximum number of concurrent requests that could be blocked/running wasm code at the same time. Since most wasm runtimes (wasmer, wasmtime, wasm3, etc.) don't currently support async or pause/resume, each active request being handled by a wasm module will block the thread running it. The executor would be like a pool of worker threads. The WasmExecutor idea was to allow multiple requests to the same wasm module to run concurrently. How does one await the result of some asynchronous actor invocation from inside a synchronous function that is not marked as an actix::main or a tokio::main or some other runtime's entry point? I've asked on Gitter and Twitter for patterns and workarounds to this problem to no avail. I've tried all kinds of shenanigans from using a map on the future to send the result out on a channel (doesn't work since nothing's polling the future that came from calling send), to using other runtimes to block_on the result (which just hangs forever). Tl dr at some vary small and crucial points in the application, I need to synchronously await the completion of a future from inside an actor's handle method that is not marked async (therefore await won't work). But, since the actor receives a message that makes an FFI call, the code inside the FFI (wasm) is synchronous and expects a synchronous result. In a call chain where everything is aware of futures, this works fine. The actor receives a request to invoke, needs to call into the wasm (which can, in turn, make outbound calls which will be satisfied by further actor calls), and then respond with the value. I've got an actor that encapsulates a struct that has a callback function over FFI (it's wrapping invocations into a WebAssembly module). The problem I'm having is that an actor system takes some inbound stimulus in order to start the massive chain of polling loops on futures, etc. So, I tried my hand at converting the codebase from heavy OS threads to actix actors. Each of these "message handling thread loops" looks a lot like an actor. This pattern is pervasive throughout my codebase.
Actix update full#
In my current codebase, I have a bunch of full OS threads ( thread::spawn) that are running select loops to receive messages on channels and reply on other channels. Actix Ingress and Egress from Actor Systems (SyncAsync Bridging) - Rust