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

✨ JS Structs working session meeting 2024-02-15 notes #19

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions meetings/notes/2024/2024-02-15.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# JS Structs working session meeting 2024-02-15

> [!NOTE]
> this was not a TG3 meeting, but a `JS Structs working session` meeting

## Attendees

- SYG
- MM
- RBN
- IID
- MAH
- RGN
- SKI
- CDA

## Notes

[WasmGC shared memory proposal][wasm] / [shared structs proposal][structs] / [convergence][convergence]

SYG: what is non-negotiable?

MM:

- conventional shared mem multithreading is to time what mem-unsafe languages are to space
- why they are bad: fault containment
- in mem-unsafe language, a flaw anywhere can cause problem anywhere else
- root causing is hard
- history of concurrent shared access from diff threads has been a disaster
- unworkable paradigm
- devs of JS working on different libs, unaware of each other
- need defensibility, fault containment
- JS is memory-safe, concurrency model in JS is communicating event loops
- agents have single thread of control
- async message passing, postMessage, fetch/xmlhttpreq
- advocating against:

SYG: I don't think I will convince you to change your philosophical viewpoint

- what is non-negotiable from the proposal?

MM:

- non-negotiable is to introduce conventional shared memory multithreading, fully exposing the hazards of that paradigm to the JS program, such that JS programs now have the burden of maintaining consistency and avoiding deadlock within that paradigm, which is inherently a cooperative path. concurrent agents all need to cooperate to prevent invariants. comm event loops is already the concurrency model, and that's where we should focus building on.
- rust shows that it is possible to support an underlying implementation utilizing techniques of shared mem multi threading, unified type system, in a way that still enables fault containment against time+space
- there are good rust compilers targeting WASM
- for JS, infeasible by any known technique to bring in sound static typing, esp for anything as sophisticated a type system as reference capabilities
- two other options:
- demonstrated by moddable XS for concurrency in embedding
- multiple agents within a realm
- embedded JS machine, all primordials immutable and stateless and have hardening operation that can make subgraph of objects transitively frozen and verifiably thread-safe
- can do async msg passing betwixt threads within the same realm
- send transitively immutable obj graphs to each other
- another option, for parallelism/speed, intel brought a data parallelism proposal
- SYG: I worked on that, it failed, I can provide postmortem

MM: reason it failed is the difficulty of bringing the right barrier requirement to the spidermonkey rope-based string impl

SYG: no, that's _one_ of the failures.

- failed because to reap benefits of parallelism, you must reach steady state for kernel immediately. this is not how js works. steady state: must get to the highest tier jit, and must stay there.
- in js, difficult. tried to warmup kernel before fanning out to threads, and they were never able to meaningfully do that
- any kind of parallelism in js is a big deal for the underlying vm to tune for
- comes down to GC and allocator
- if allocation is a serialization point, which at the time, spidermonkey was

RBN:

- MM said earlier that programmers of normal skill can cause issues if not enough guardrails around shared mem multi-threading
- I don't disagree, but that ends up discouraging sophisticated devs with large scale apps that need to use this
- large apps are starting to need these capabilities and performance
- if I'm building an app and running into perf blockers with postMessage, or want to work with lockfree algos to write fast code, then I can't use JS
- that's unfortunate because that limits where you can go with JS. I have to use a different language

MM: the point of this proposal is coexistence with WASM

SYG: that's not the motivation, it's a requirement of the proposal to work with WASM

MM: if you try to keep enlarging JS to accommodate all paradigms, then we're already over our complexity budget w/o this proposal

SYG: this is not a niche paradigm

MM: JS is not a greenfield language; it was designed around a set of paradigms, grown around this set of paradigms and has already grown beyond it's complexity budget

SYG: I'm not going to convince you re: philosophy. JS memory model admits this, there is a weak memory model for JS for interop with WASM; we are already in this world. the argument that JS is programmers is for a certain skill level insulting to say they should not use the paradigm and that doing it in JS is prevented for purity reasons from committee members

MM: JS is for programmers of a very-wide range of skills. a lot of my activity of m

SYG: we're not shoving this down throats of devs to use this

MM: yes you are

SYG: why hasn't the contagion happened since we shipped memory model? we built in a very large and hard to get through gate on web platform called cross origin isolation, for all threads within a webpage, saying your server must explicitly opt in, send headers, for any shared memory multithreading. whether you want to use shared array buffers, high freq performance.now, must opt in. off by default. difficult to opt in. sophisticated web apps are taking a long time to audit and rearchitect their apps to opt in so that they can use shared mem multithreading. lib contagion has not happened because of this, and you must jump through a lot of hoops. you can't just bundle an npm pkg that uses shared mem multi threading into a web app. it won't work

MM: require explicit opt-in from outside the agent

IID: spidermonkey willing to listen to argument that perf is needed, but there is a lot of work involved and this is a fairly niche feature. not excited about implementing it differently for WASM vs JS

SYG: agree on niche. we have sophisticated product teams that have billions of users, and the number of apps to leverage is small, but impact is large

RBN: fine with adding additional gate/ceremony to use

SYG: we are stewards of the platform. customers are apps. this is next perf frontier.

MM: for teams that want shared mem multithreading, and WASM is viable target, why don't people use another language that targets WASM and makes use of shared mem multithreading

SYG: they're doing that

MAH: at some point, someone is going to come along and force orgs to enable shared memory. attack vector where org doesn't understand the risk, doesn't know what they're doing

SYG: if they don't understand the risks, we can't put guardrails on the world

SYG: one of the ways we cannot do better than linear today, is that SABs must be rewrapped

SYG: can't scale program w/ number of threads. need to copy entire wrapper graph. e.g. in spreadsheet app, state of cells is kept in main memory, each cell is comprised of many objects, tracking formulae, etc. obj graph for that app is very large. many wrappers. proposal for WASMGC is to share that. must be able to share objects themselves. non-negotiable that shared wasmgc structs are actually shared, maintain identity, one obj in heap, shared across threads

IID: concern of spidermonkey: there will be a variety of overhead, needing more barriers, synchronization, etc. and that will eat into some perf wins, esp because no shared to local restriction, end up pulling state into shared space even if not accessed from multiple threads. one failure mode is the overhead you need for safe-ish multithreading, can eat into the perf wins of the multithreading. wrappers can destroy benefits of parallelism.

RBN: was working with dev trial, parallelizing TS. we only produce new nodes during parsing, transform, but once we have AST nodes, they are immutable, so don't have concerns with data races causing mutations. we found a problem that to use effectively, need to attach behavior, and that required thread local prototype. without that, to take ast structure, we parse in parallel and give to users for public APIs, then it must look like a normal obj. else, need to wrap entire shared struct with a non-shared wrapper, which double the memory alloc. and these users are building very large apps. can run OOM. need to scale, and these wrappers become memory concern, plus needing proxies, etc which slow down, double mem use

RBN: rehydrating means additional overhead

[wasm]: https://github.com/WebAssembly/shared-everything-threads/blob/main/proposals/shared-everything-threads/Overview.md
[structs]: https://github.com/tc39/proposal-structs
[convergence]: https://docs.google.com/presentation/d/1j0W_mFaR8wEBqgBPRzJ0h4-lmgl87U92TQeokfy0N2w/edit#slide=id.gc6f889893_0_0
Loading