-
Notifications
You must be signed in to change notification settings - Fork 322
Experiment with native /internal/shared dir for Playground CLI #2446
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
base: trunk
Are you sure you want to change the base?
Experiment with native /internal/shared dir for Playground CLI #2446
Conversation
With Planning to look at this more tomorrow. |
Currently, the Blueprints v1 worker's |
Yeah, the errno is |
Yeah we might need to rewire some of the /internal initialization logic for a secondary worker when using Blueprints v1 to support this. |
This is a functional experiment now, and Playground CLI multi-worker boot feels nearly instantaneous on my laptop. It requires rebuilding php-wasm/node, which I plan to do after lunch. NOTE: |
@adamziel, the only issue appears to have been creating the initial dirs under |
Some things that need done:
|
This isn't ready to merge, but it is ready for more feedback. |
This is simple and effective, I like it. Thank you @brandonpayton!
This is a good idea. There will be some cases where that auto-cleanup won't run, e.g. the process gets killed without waiting, there's a power outage etc. I wonder what are some things we could do to maximize our chances of actually cleaning up stale directories. Perhaps we could use a naming pattern including PID and then sweep stale directories on startup? There could be some risk with short-lived processes so maybe a |
Poking around more, we'll need to address all these paths: wordpress-playground/packages/playground/wordpress/src/boot.ts Lines 232 to 236 in 89a7f30
Ideally, we can either get rid of Also, we need to take this bit of the PHP class into account (in
|
Noodling on this more, perhaps a useful API would be something like
In any case, I've instrumented the Blueprints v2 worker code and the workers seem to boot fairly quickly. I don't have any numbers to quote but it feels fast! |
@@ -3914,6 +3912,8 @@ export function init(RuntimeName, PHPLoader) { | |||
node = lookup.node; | |||
|
|||
if (FS.isMountpoint(node)) { | |||
console.log({ mountpoint }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I accidentally reformatted the file. My changes here are all about this and the following two console.log
s.
This comment responds to multiple comments, not necessarily in the order they were made.
Nice! Thanks for adding that. Yeah, that's been my experience as well.
@adamziel, what if we invert this? It seems like we want all workers to respond to requests based on the same state. What FS paths do we want to be private/separate per worker?
Ah, good points! It's obvious we'd want to stop proxying already-shared filesystems (and same for copying from old to new PHP instances during hot swap), but somehow I was forgetting that. |
Oh I like it! Off the top of my head, it's just the input/output devices. It seems like we could share everything else 🤔 So these paths would become worker-specific:
We could move them to /internal/isolated (as opposed to /internal/shared to keep the /internal/shared path working for existing API consumers) and share the rest of the filesystem. |
Sweet. I'm looking at doing this. Using /internal/isolated seems a bit tricky to do with Emscripten mounting because it doesn't look like we can easily mount a MEMFS dir inside a NODEFS dir. At least Google suggests we probably cannot easily do this because it would mean mixing contents of a real NODEFS dir with artificial mounts in that dir. Based on my recent looks into emscripten FS implementations, I found this reasoning compelling, but I haven't tested it. If that is truly an issue, we will likely run into trouble if trying to mount a NODEFS dir as a subdir of our default/temp NODEFS dir. Then again, how does wp-now do this today for automounted subdirs of /wordpress ? Will test and follow up here. |
OK, I guess we can forget that. In testing, it seems totally possible. I can mount a real dir as /wordpress and then mount another as /wordpress/wp-content on top of that. |
Ah, that wasn't mounting a MEMFS dir within a NODEFS dir, but I just tested that by editing a php_8_3.js file and mounting a MEMFS dir inside NODEFS like: if (phpWasmInitOptions?.nativeInternalDirPath) {
FS.mount(
FS.filesystems.NODEFS,
{ root: phpWasmInitOptions.nativeInternalDirPath },
'/internal/shared'
);
FS.mkdir('/internal/shared/something');
FS.mount(
FS.filesystems.MEMFS,
{ root: phpWasmInitOptions.nativeInternalDirPath },
'/internal/shared/something'
);
} And there are no errors during boot. So this should all be doable. 👍 |
Random thing, when I was thinking of adjusting the directory trees to workaround possibly mount challenges, I was thinking something like:
@adamziel how does this sound to you? I kinda like it, at least compared to nesting non-shared things in a shared dir. |
I'm out of time today and plan to continue tomorrow. |
Cool. It looks like we already skip any FS node that is not detected as MEMFS: wordpress-playground/packages/php-wasm/universal/src/lib/php.ts Lines 1457 to 1461 in 533d676
|
Sounds good to me! I want to preserve the directory structure inside the |
Ah! Thanks, that's good to know. I was tempted to get rid of |
I made changes to share both Planning to continue debugging on Monday. |
I've been thinking about this but have left it alone so far. |
Funny. It turns out the bug I'm seeing is a failed attempt to proxy /internal since it is now already mounted during wasm init. 🤔 I wonder whether we can keep the same proxy paths but just make a proxying function that only proxies if there is not already a mount at that path. On the other hand, it may be stronger and safer to require explicitly declaring shared/isolated paths. |
Instead of this, I ended up only passing the native internal dir path to the primary PHP process. The secondary PHP processes can continue proxying to the primary PHP process /internal dir. |
Do we have to proxy at all if we can use native mounts? I suppose we do, at least in the web version, so maybe it makes sense to keep that logic consistent in the Node.js version 🤔 That's probably too big for this PR, but I wonder if we could decouple PHP and the Filesystem, as in have a FS-only WASM module to use as a source of truth, and proxy directories from both the "primary" and "secondary" PHP instances there. That might allow us to remove the distinction between the primary and secondary and use just identical workers. |
28636f7
to
91dc4b0
Compare
That's worth considering!
That sounds good. Before this PR, we needed to pick an initial worker for running the Blueprint, run the Blueprint, and then copy the /internal results to the other workers. After this PR, even while applying the Blueprint during boot, there wouldn't need to be any special difference between the workers and PHP processes within the workers. |
@adamziel, I haven't really considered the |
Some things that are left:
Bonus:
|
Motivation for the change, related issues
There are two reasons to mount a real directory as
/internal/shared
:/internal/shared
to be truly shared between all PHP instances/internal
dir and unzipping for secondary workers is making multi-worker CLI startup quite slowRelated to #2419
Implementation details
TBD
Testing Instructions (or ideally a Blueprint)
TBD