TraceMachina / nativelink

🔥🔥🔥 Bazel RBE with CAS server implementation in Rust. The free and open source cache and remote execution service, prioritizing stability and speed for the people that need it.
https://docs.nativelink.com
Apache License 2.0
232 stars 45 forks source link

Make WASM compatible binary optimized for edge computing #124

Open allada opened 12 months ago

allada commented 12 months ago

As outlined in #116, WASM could be very useful for edge-computing services. Since many of the bazel files are likely to live in S3, redis or other similar layers, it would likely save money, time and effort if users could hit a local edge point, a WASM module starts up, runs the tasks, then powers down. Since these kind of services would be data transformations the compute and resources would likely be low.

allada commented 12 months ago

Adding wasm support looks like it'll be a bit of a pain. tokio especially is heavily integrated into everything and it does not have an easy way to say certain packages need certain features out of a an external package. For example, memory_store does not need filesystem stuff, but it has to bring it in because it uses tokio and tokio::fs is used by filesystem_store.

aaronmondal commented 12 months ago

Yep, I've also just encountered this. The big "blockers" seem to be sockets and filesystems.

Regarding sockets, examples exist, e.g. at https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/samples/socket-api/README.md, but it seems like that's still fairly custom and actual standardization efforts are still going on at https://github.com/WebAssembly/wasi-sockets/.

Regarding filesystems, it seems that sys::fs supports the wasm32-wasi target. But that's quite different from tokio::fs. This has surely has performance implications, but I'm not sure whether that's in the good or bad sense. Benchmarks exist that show sys::fs to be a lot faster in some scenarios, but async tokio::fs to be friendlier to parallel invocations.

@allada Do you have any thoughts on how this could be benchmarked effectively? What is the thing that we'd want to optimize for? At first glance it seems to me that some builds could benefit more from sys::fs while others would benefit more from tokio::fs. Is this correct? If all artifacts were stored in "external" DBs, be it some in-memory kv-store or S3, is there a scenario where we could "disable" filesystem support entirely?

aaronmondal commented 12 months ago

It might make sense to aim for configurability of certain features, similar to how crates can have different features. In Bazel that's pretty straightforward to implement nowadays, as config_settings are really nice for building and testing different configurations in a CI-friendly manner, e.g. https://github.com/llvm/llvm-project/commit/a268127736e4d703cef8c9f4841f9a8e8ac21ba7#diff-53a2390dee6b4312d192975c47ca66a373acc56163816ff2145b036b846d0b1b.

allada commented 12 months ago

I'm actually not worried about filesystem or sockets, we can just disable them for now. GRPC is likely to be a big concern, since it does it's own thing, so we may need to do a bit of upstreaming to manage it. It's unlikely they'd accept any PRs unless the WASI folks got their spec nailed down. We could do a bit of hacking by forking/patching and targeting our version, but I'm not a fan of that idea.

I actually think the bigger issue is going to be selectively disabling cargo features for specific targets. I did not see a straight forward way of doing this without a lot of hacky things. This use-case might be a good thing to bring up to the cargo_universe maintainers as a use case for disabling cargo features with configurations.