Open SoniEx2 opened 1 month ago
Coincidentally, I came across that dissertation recently and, vaguely liking modal logic myself, put it into my reading queue :) Also, they use the word "worlds" in a way that feels complementary to WIT world
s. That being said, I don't know what concrete implications there would be for the Component Model. Components are not meant to be coupled to or opinionated about distributed computing (it's an early non-goal), so I wonder if the right place for this sort of reasoning about worlds and local and remote resources is at a higher layer that is fully focused on the challenges (and fallacies) of distributed computing and embeds the Component Model as a lower layer that provides computational primitives. But I'd be interested to hear any more specific ideas you have.
hmm...
in which case, we should maybe explicitly move threads out of component model MVP?
also yes, they use "worlds", but as far as we can tell they're nothing like WIT worlds. they're more like the opposite, really: tom7's "worlds" are shared-nothing by default, they act more like isolation boundaries (as threads should be), while WIT's "worlds" seem more intended to be composable, such that you can use/pull in multiple worlds at the same time, with no boundaries between them (wanna share memory? wanna share functions? wanna share globals? go ahead, you can share whatever you want between them).
also, we should note that we aren't asking component model to solve distributed computing - we're asking it to enable WASI to solve it.
(in fact, we would rather have competing solutions, because we don't believe there is an one-size-fits-all solution for distributed computing. after all... multithreading is one of them.)
in which case, we should maybe explicitly move threads out of component model MVP?
FWIW, thread.new
is 🧵-gated in the current proposal to reflect the fact that it's not fully spec'd or implemented; at this point it's more of a plan-of-record and more work is necessary to get it shippable. If it doesn't get fully speced+implemented by 1.0/MVP, it'll get bumped to a post-MVP release.
But I think there is a useful difference between the shared-nothing kind of threading that naturally arises in distributed systems (where the parallelism and shared-nothing-ness are natural consequences of running on separate machines) and the shared-everything kind of parallelism provided by thread.new
that assumes running in a single address space on a single machine. I think both are useful and complementary, but I'm hoping we can keep thread.new
a component-internal implementation choice that we keep from messing with other components by carefully specifying the rules for cross-component calls (analogous to what we're currently doing with sync-vs-async).
also yes, they use "worlds", but as far as we can tell they're nothing like WIT worlds. they're more like the opposite, really: tom7's "worlds" are shared-nothing by default, they act more like isolation boundaries
WIT worlds are also shared-nothing, as they desugar to component-model types, and component are shared-nothing.
but thread.new (and wasm threads) isn't actually shared-everything. it can share memory, but not full module instances. (unless we misunderstand the threading proposal?)
regardless, it's still easier to add sharing to a shared-nothing system than to remove sharing from a shared-everything system.
also we guess we don't understand WIT worlds. can't you mix and match them? (e.g. implement both wasi-cli and uh... wasi-http?)
but thread.new (and wasm threads) isn't actually shared-everything. it can share memory, but not full module instances. (unless we misunderstand the threading proposal?)
By having thread.spawn
take a function of type (func shared (param i32))
, we mean to leverage the shared-everything-threads proposal which defines shared
for func
(and other) types, with the net effect being that the current instance and its contents are shared when the function is executed on a new thread.
also we guess we don't understand WIT worlds. can't you mix and match them? (e.g. implement both wasi-cli and uh... wasi-http?)
Yep, worlds can be unioned (e.g., via include
). But shared-nothing-ness is preserved by this operation.
hmm...
yes, we see. okay, shared-everything-threads looks useful for the particulars of threads, but... hmm...
one of the things the current component model does is that you instantiate modules and components in the component model. the biggest change we can think of that would solve distributed computing is to let the host instantiate modules, as not all modules would be compatible with every environment the code is meant to run in. (for example, a browser does not have filesystem access. the host can provide message passing between instances, and then an instance would be created on the browser, without filesystem access, separate from the instance on the server. the instances would have different capabilities.) this would be very natural in the old instance-per-module system. by focusing entirely on shared-everything-threads, component model may have lost the ability to support this use-case.
and WASI was all about capabilities in the early days so it'd be nice to see more of that again.
I believe the capability model of the host being able to supply different capabilities to different components when instantiated remains the same with the addition of thread.spawn
; the "everything" that is shared only refers to the core module instances (and their memories, tables, globals, functions) that are encapsulated by a single component instance (as an impl detail of that component instance).
we would argue the problem is the assumption of everything under a single component instance being shared.
why would you want that to be true?
The core wasm code inside a component would still have to opt into shared-everything-threads by marking all relevant core memories, functions, tables, etc with shared
(as required by the validation rules for shared
introduced by the shared-everything-threads proposal) as well as adding some (TBD) shared
canonopt
to the canon lift
definitions that export core wasm functions to the outside world. Thus, non-shared
wasm would be the default option.
This is a link to tom7's amazing PhD: http://tom7.org/papers/modal-types-for-mobile-code.pdf
As the PhD says, it's about "modal types for mobile code". We see it as an alternative to the threading model provided by component model's thread.spawn.
Importantly, while modal types can be trivially used for threads, they can also be extended beyond threads, into the areas of heterogeneous computing. This includes, for example:
So, the main use case for modal components is to provide threads without providing threads. It's basically a generic API for providing things that work like threads. Because, whether you like it or not, threads are mobile code. (With shared-ish memory, but we can just extend the model for that, it doesn't have to be shared-nothing.) But it can also do other things. In fact, you could even use the same modal component API for system-equivalent subprocesses, like popen and stuff.