For this case it's complicated because some runtime supports https://github.com/WebAssembly/threads which mostly contains things like the spec for atomic but not the actual "threads" specs and then some runtimes (i.e wasmtime) also supports https://github.com/WebAssembly/wasi-threads which is one version of the threads. But a new proposal came into play https://github.com/abrown/thread-spawn so ... it's complicated.
I still build a single-threaded binary for Firefox, and fallback to it if `SharedArrayBuffer` is `undefined` or if the `WebAssembly.Memory` constructor fails (some iOS devices might throw when `shared` is `true` due to a bug).
So instead of:
`host -> call foo on guest -> return to host`
`host -> call guest main -> call foo on host -> host returns when ready -> guest calls foo when done`
FWIW the scheduler (so goroutines) don't work in go if you're not calling from an main, so anytime you call a custom export then try to use a goroutine you'll get panics.
10x size is about the blowup we see as well. It's also likely to be slower (some of the Tinygo authors said ~20% slowdown compared to tinygo) probably due to the simpler/smaller runtime and LLVM being better at optimizing.
Rust (or really anything LLVM backed) is still probably the best WASM language in terms of performance and support, but .NET (don't forget to turn on AOT) is starting to get really good too (except for the fact that .NET compiler barfs out a bazillion files that the browser needs vs. 1 self contained .js or .wasm file which sucks if you are trying to build a self contained library like OpenCV.js)
Can to elaborate?
This is can be true if you're interacting with browser API's such as the DOM frequently, because there's an overhead.
But I've seen several projects where (non-GC) WASM has improved performance significantly for specific tasks. You won't get native performance obviously.
The overhead of a runtime can easily make WASM code run slower than native JS functions. This only applies to GC languages like Go which require that.
>But I've seen several projects where (non-GC) WASM has improved performance significantly for specific tasks. You won't get native performance obviously.
You absolutely can if you're writing the raw WASM or compiling from C.
When I measured C compiled with clang -O3 vs JS performance the only noteworthy speedup were on math-heavy tasks and even there only for integer-heavy math (floating point math was better than JS, but not by much). In a few cases the performance was worse. Notably recursive algorithms were _much_ better in WASM though even with algorithms that can't have tail-call optimisation (I guess function invocation has a lot of overhead in JS compared to C)
I think people over-value WASM speed. With regards to performance I imagine that the biggest gains compared to JS would be from not using garbage collection language. GC overhead, especially JS GC (compared to golang GC) can be painful in very large applications, especially in things were timings matter like 3d rendering. But GC can be optimised for in JS by avoiding allocations in the critical paths of the app
Is it an edge play for using something like Cloudflare Workers?
Is it cheaper vs standard serverless/container deployments? Go apps can already scale to 0 for these use cases.
There's also other benefits. Example: the team I work on compiled Kyverno, a CNCF K8s policy engine written in Go, to a WASI target. We are building Kubewarden, a CNCF policy engine where policies are Wasm binaries shipped in OCI registries. We strive to build "a Universal Policy Engine". Now, we have an experimental Kubewarden policy `kyverno-dsl-policy` that allows you to reuse Kyverno DSL with us. We also provide WaPC as a target, more performant and secure, hence normal SDKs for Go, Rust, C#, swift, typescript... In addition to supporting Rego, again compiled to Wasm.
IMHO you only benefit from the real sandboxing from WaPC, as WASI's posix-like interface allows you to attack the host.
The next step for the official Go compiler is to export the function symbols, to allow for WaPC.
In a nutshell, with Kubewarden we strive to build the universal policy engine by:
- Provide all personas (policy consumer, policy developer, policy distributor, engine admin, engine developer/integrator, etc) with current and future industry-standard workflows, not only a subset of personas, nor more than needed knowledge for those personas. It's a bold statement, and if it would be universal it should indeed cater to everyone.
- This is achieved with policies as code, which are Wasm modules: Wasm policies allows us to support Rego DSL (OPA/Gatekeeper), YAML, SDKs for Wasm-compiled languages, and now an experimental Kyverno DSL policy by compiling it to WASM with WASI. Great for using your language and tools of preference.
- Wasm modules have first class support In OCI registries, just like container images: Use same tools that you know as artifact distributor: SBOMs, signing and verifying with cosign, airgap, slsa.dev, etc.
- Policies can be evaluated out-of-cluster: great for CI/CD, dev loop, integration tests, etc.
- Modular architecture informed by using Wasm policies: OCI registry, policy-server, k8s controller, out-of-cluster cli (kwctl), etc. This also helps in adopting future industry-standard workflows.
- Usual features of a Policy engine (mutating, context-aware, recurring scanner of already in-cluster resources, etc). Plus ample room for new features thanks to the architecture. E.g: possibility to run the policy-server directly in the k8s apiserver (one colleague already presented that in Kubecon), possibility to evaluate out-of-cluster policies outside of clusters like OPA just by running the policy-server standalone, more DSLs compiled to Wasm, more languages, etc.
- Vendor neutral, CNCF project, open source, developed in the open.
1. Could be an edge/iot play (tho not with standard go toolchain bc those binaries are huge and slow)
2. Trusted environment makes it interesting for all kinds of sbom-related usecases. Think weapons tech, space, etc
3. On the container side things are less clear to me but may offer better startup time, reduced footprint etc
4. Finally, for plugabble software it’s most interesting option personally. It’s basically 2.) but with focus on DX over security
My understanding is as follows:
WASM - a portable, platform-independent virtual machine for executing a "web assembly"
WASI - an extension to the virtual machine that adds APIs for interacting with the system and breaks all the WASM sandboxing (presumably NOT platform-independent?)
Is the point of this addition to Go that I can now target "WASM implementations that have WASI" with Go source code compiled to WASM?Why would someone want to do that? Just for edge functions in cloud workers?
You should go watch any of the numerous blackhat presentations on wasm or just talk to some of the security researchers out there. You can do attacks that most people haven't been able to do for 20+ years.
Wasm has horrible security.
This is a bad and roundabout way to say that vulnerabilities in WebAssembly modules may still cause a corruption in their linear memory. Which is absolutely true, but those attacks still matter today (not everyone turns ASLR on) and similar defences also apply. In the future multiple memories [1] should make it much easier to guard against remaining issues. WebAssembly is a lucrative target only because it is so widespread and relatively young, not because it has horrible security (you don't know how the actually horrible security looks like).
[1] https://github.com/WebAssembly/multi-memory/blob/main/propos...
There are also other things of great value, for example providing a way to write plugins for cloud-based SaaS solutions, as in you compile your binary, hand it over to your SaaS service and the service itself runs your binary when some event happens. Basically plugins for cloud based stuff, much more powerful and simpler than Web Hooks.
Another example was to write custom database functions, for example, adding a complex math function to postgres so you can do "SELECT myFunc(COLUMN_A, COLUMN_B) FROM TABLE".
Another example was to sandbox plugins for desktop applications (including mods for video games), plugins are a huge security issue when it is native code running in your machine.
These plugin examples the entity that is running the plugin code can limit the syscalls used by your WASI-compatible WASM binary so you don't allow, for example, your video game mod to read/write files outside a specific folder in the file-system
https://github.com/bytecodealliance/wasmtime/blob/main/docs/...