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

Modal components #400

Open
SoniEx2 opened this issue Sep 25, 2024 · 10 comments
Open

Modal components #400

SoniEx2 opened this issue Sep 25, 2024 · 10 comments

Comments

@SoniEx2
Copy link

SoniEx2 commented Sep 25, 2024

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:

  • An async-signal safety model, for WASI users who really want to shoot themselves in the foot, like ourselves.
  • Possible other cases like bridging across the client-server model. Not that anyone would ever actually use this, but it's fun to talk/think about.

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.

@lukewagner
Copy link
Member

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 worlds. 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.

@SoniEx2
Copy link
Author

SoniEx2 commented Sep 30, 2024

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).

@SoniEx2
Copy link
Author

SoniEx2 commented Oct 1, 2024

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.)

@lukewagner
Copy link
Member

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.

@SoniEx2
Copy link
Author

SoniEx2 commented Oct 1, 2024

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?)

@lukewagner
Copy link
Member

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.

@SoniEx2
Copy link
Author

SoniEx2 commented Oct 1, 2024

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.

@lukewagner
Copy link
Member

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).

@SoniEx2
Copy link
Author

SoniEx2 commented Oct 2, 2024

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?

@lukewagner
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants