Skip to content

Commit

Permalink
docs(wasi): notes WASI-01-23.md
Browse files Browse the repository at this point in the history
  • Loading branch information
ricochet committed Feb 5, 2025
1 parent 7b9d597 commit d4eb520
Showing 1 changed file with 93 additions and 0 deletions.
93 changes: 93 additions & 0 deletions wasi/2025/WASI-01-23.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,96 @@ The meeting will be on a zoom.us video conference.
1. Pat Hickey: succession of my WASI Co-chair seat at [CG-01-28](../../main/2025/CG-01=2028.md)
1. Proposals and discussions
1. Summary of Component Model 0.3 progress thus far, discussion of remaining bits for a 0.3.0 release (30min, @dicej, @lukewagner, [slides](https://docs.google.com/presentation/d/1Is0yTZ13xuw5UjbbUH_h33HVqVEjDV3XDzQFWmUHolg))

## Notes

### Attendees

- Bailey Hayes
- Joel Dice
- Jeff Charles
- Colin Murphy
- Stephen Berard
- Oscar Spencer
- Alex Crichton
- Rahul Chaphalkar
- Chris Woods
- Hendrickson
- Kevin Moore
- Andrew Brown
- Mendy Berger
- Luke Wagner
- Laura Hendrickson
- Marcin Kolny
- Thomas Trenner
- Till Schneidereit
- Yosh Wuyts
- Pat Hickey
- Dan Gohman
- Mike Warres
- Kate Goldenring
- Mossaka

### Announcements

#### WASI Co-chair

**Pat Hickey**: Served two years as co-chair and will be stepping down. Intend to be succeeded by Yosh Wuyts, please attend the CG meeting Tuesday to vote on that.

### Proposals and discussions

#### Summary of Component Model 0.3 progress

**Luke Wagner**: Outline: first a 0.3.0, then a series of minor releases that add more on. First, status of 0.3.0 spec from me, then status of the implementations from Joel, and finally I’ll talk about the features that are put off until 0.3.x.

Luke: Most wasi interfaces need concurrency, in 0.2 its complex, suboptimal, requires lots of manual work, prevents component composition, and makes you choose a function color. Goal of 0.3 allows func to be implemented and/or called asynchronously. Add explicit stream and future types to use in func param and results. Efficient memory sharing ABI for streams. See for more: my Wasm I/O talk and Async.md explainer in CM repo.

Luke: Progress is to split CM 0.3 features into 0.3.0, released ASAP (March is a goal people are converging on). Future and stream types, and async canonical ABI option. Implemented in Wasmtime and JCO polyfill at first. Make enough progress that we can successfully use this from a variety of languages: go, js, rust, .net, python, libc. Enough progress at CM level to enable a WASI 0.3.0 release, which most notably removes wasi:io, and all the pseudo-futures in the 0.2 interfaces.

Luke: Then 0.3.x would follow the train model, high value additions that are additive, goal is to unblock people to do parallel work and gather feedback. Cancellation, cooperative threads, stream optimizations, caller-supplied buffers, and expansion of types passed to stream/future to expand error cases.

Joel: we’re still thinking of WASI 0.3.0 as being a superset of WASI 0.2.x, so removing wasi:io from 0.3 doesnt mean that WASI 0.2 will be broken

Luke: Yes the 0.2 interfaces will remain alongside the 0.3. At later points theres an option to virtualize 0.2 in terms of 0.3 but thats not required to launch.

Luke: Merged into the CM repo for 0.3.0: the async ABI option for lifting and lowering, and how sync/async combos are expected to work. Future/stream/error-context type constructors. Generalization at canonical ABI level of a waitable set. Two pending PRs: non-blocking attribute thats a hint to bindings generators that this wont ever block but has no semantics in the runtime. Specify how async works for start functions, and how that can express a background task. Remaining to be done: Allow zero-length in stream read/write for nonblocking IO. Let one task wait on another inside the same component, as opposed by IO.

Joel: I’ve been busy: wasm-tools and wit-bindgen implementation now has async/streams/futures, wasmtime is in the process of being merged. This doesn’t yet have the waitable sets and other in progress stuff Luke called out. Next steps: need JCO support, Roman has started working on WASI p3 host support in wasmtime-wasi, prototyping support in wasi-libc which motivated the waitable sets, and finally make sure implementations are synced up with the spec changes in flight.

Thomas Trenner: Can you elaborate on wasi-libc?

Joel: wasi-libc builds separate sysroots for WASI p1, WASI P1 + threads, and WASI P2. The expectation is it will make a fourth sysroot for WASI P3. In particular, socket support in P3 will use streams and futures for a more efficient implementation than possible in P2. Part of the WASI P2 support leans on the P1->P2 adapter, goal is for the P3 sysroot to be standalone without P1 eventually but it may leverage a P1->P3 adapter to get it shipped.

Thomas: So you can choose which feature you want when you use libc?

Joel: Yes the target will select which version of WASI you target.

Pat: clarification on adapter. These are tech debt. Tech debt is useful to get things shipped but we have to pay it off later.

Luke: 0.3.x features after 0.3.0 ships. Cancellation is a lesson learned in many async ecosystems. You can always cancel as a consumer of a future or stream, but as the producer you need more language integration. We want to have this spec’d before 0.3.0 in case it would require a breaking change.

Luke: Cooperative threads: 0.3 gives us stack-switching in the host, just like JSPI. This could be used to implement threads without terrible asyncify overhead - explicit yields and call outs in CM can be used as yield points. This can get us threading code working before shared-everything-threads arrives. Some platforms won’t want to give wasm real threads (e.g. proxies, serverless, UDF) so this allows code to run without running in parallel. Idea is to take the existing thread.spawn primitive and add a shared attribute, if the attribute is absent you get a cooperative thread. Mostly the same code/abi, swap out a few key pthread/atomic implementation bits. We need to do all this work for real shared-everything-threads so this is a step forward to that goal.

Joel: potentially a host could choose to implement a thread spawn with shared=true, they could insert yield points and implement it with cooperative threads. If shared is absent that is the guest saying its prepared only for cooperative threads. Deterministic scheduling makes fuzzing feasible.

Chris: Won’t this lead to unexpected developer behavior like early windows?

Luke: If you have those long-running loops - in a lot of contexts you don't have those like serverless - but the runtime can insert yield points, rather than the developer needing to do so.

Chris: doesn’t thread mean parallelism?

Luke: it would literally implement pthread api, so it would work exactly like a thread without parallelism. If you run multithreaded applications on a single core you also dont get parallelism, but the same code works.

Luke: Stream optimizations. wasi:io/streams have forward/splice, skip, write-zeroes. We can add those back in as canonical abi builtins on streams. We should be able to create a stream from some part of the data segment. Maybe that data segment never had to even get written to linear memory, to eliminate a double copy. Lulls (no more coming for a while, aka flush, not implying written to disk). React server streaming wanted this added to web streams.

Luke: Caller supplied buffers. Already streams give a certain amount of caller supplied buffers, but it doesn't cover every use cases. If you want to get rid of realloc, lazy lowering ABI, enables single module components. Readable-buffer/writable-buffer as CM primitives, not just as top level types like stream/future but also nested inside records or variants, a way to pass in a pointer with abstraction to protect it.

Frank: What about synchronization between provider and consumer of these buffers?

Luke: Whenever passing buffers there's a question of how long the callee can hold on and write into it? The caller passes these pointers when the call starts, when the call ends the caller knows the callee has lost access to those buffers, and the caller knows how much has been read/written to them during the call. You can think of these buffers as the primitive below a stream, a stream is where one side gets a sequence of readable buffers and the other a sequence of writable buffers

Luke: Stream<T, SuccessT?, ErrorT?> / Future<T, ErrorT?> How do we signal errors for reporting/logging, other times we want to ignore them? E.g. at the end of an http body you might get trailers. Sometimes the error type is a fixed variant so the consumer can recover. 0.3.0 can’t express this yet without also passing a future that resolves when the stream is done, this pattern comes up in many places. Split operation that takes a stream<T,S,E> into (stream<T>, future<S, E>). On error the stream<T, S, E> can send the same error-context to the split stream<T> and future<S, E>.

### Final Announcements

Yosh: I want to call attention to my crate `wstd` that Pat Hickey and Dan Gohman have been contributing to. 0.5 was just published, its an async runtime for rust targeting WASI 0.2.

0 comments on commit d4eb520

Please sign in to comment.