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

PHP: Reduce memory requirements – lower the HEAP size from 1GB #1233

Open
adamziel opened this issue Apr 12, 2024 · 0 comments
Open

PHP: Reduce memory requirements – lower the HEAP size from 1GB #1233

adamziel opened this issue Apr 12, 2024 · 0 comments
Labels

Comments

@adamziel
Copy link
Collaborator

adamziel commented Apr 12, 2024

Warning

This is more important since Loopback Request Support landed as we're now creating more PHP instances.

PHP is currently compiled to allocate 1024M of memory when it boots, and it limits the number of Playgrounds you can run concurrently especially on low-resource devices:

Let's see how low can we go while still keeping 256M available for running requests.

Importantly, MEMFS files are also kept at heap. I wonder what else is.

Resources

Discussions related to measuring memory usage

Related to

@brandonpayton @ellatrix

@adamziel adamziel added this to the User Experience milestone Apr 12, 2024
adamziel added a commit that referenced this issue Apr 25, 2024
Adds support for PHP spawning more PHP instances:

```ts

const handler = new PHPRequestHandler({
	documentRoot: '/',
	phpFactory: async ({ isPrimary }) => {
		const php = await createPhp(requestHandler);
		if (!isPrimary) {
			proxyFileSystem(
				await requestHandler.getPrimaryPhp(),
				php,
				requestHandler.documentRoot
			);
		}
		return php;
	},
	maxPhpInstances: 2,
});
const php = await handler.getPrimaryPhp();
php.writeFile('/second-script.php', `<?php echo 'Hi from another PHP instance!';`);
php.writeFile(
	'/main.php',
	`<?php 
		require "/wordpress/load.php"; 

		// Can send HTTP requests to self
		echo file_get_contents( get_site_url() . '/second-script.php' );

		// Can execute PHP scripts
		echo exec( 'php /second-script.php ); 
	`
})

await startLocalServer( handler );
await handler.request({ url: '/main.php', });
```

Without this PR, we only have a single PHP instance running. If that
instance needs to run another PHP script while it's running, it will get
error 502 as there's no other PHP instance available to handle that.

Closes #1182
Closes #1177

## Technical implementation

This PR draws a clear line between BaesPHP and PHPRequestHandler.

Before this PR, BasePHP could be given a `serverOptions` argument and it
would create a `new PHPRequestHandler` as a convenience. After this PR,
BasePHP longer instantiates `PHPRequestHandler`. Why? Two reasons:

* We may have multiple PHP instances but only ever want a single
`PHPRequestHandler` to orchestrate them.
* `PHPRequestHandler` must know how to start new PHP instances, but
BasePHP shouldn't be concerned with that at all.
separates PHP leverages two major building blocks:

Furthermore, `PHPRequestHandler` now uses
[PHPProcessManager](#1301)
to spawn new PHP instances on demand. To create a new request handler,
you now need to pass a `processManager` instance or, alternatively, a
`phpFactory` function.

Ideally, `BasePHP` would have no more references to `PHPRequestHandler`
after this PR, but unfortunately we cannot fully decouple the two just
yet. `BasePHP` exposes an `absoluteUrl`, `documentRoot`, and a `request`
method that are used by Blueprints, and Blueprint steps only get a
`BasePHP` instance without any extra contextual information. This will
be easier to resolve once we switch to [PHP
Blueprints](https://github.com/WordPress/blueprints-library/) where
we'll never call `php.request()` and we'll also be able to access these
contextual information via `$_SERVER` and such.

## Follow up work

* #1233
* Create a separate, minimal Emscripten module as a source of the
Filesystem. Remove the concept of a "primary" PHP instance.
* Decouple BasePHP from the PHPRequestHandler. The dependencies are
super intertwined now – BasePHP needs a PHPRequestHandler instance, but
PHPRequestHandler acts on BasePHP. PHPProcessManager needs both, but
also configuring a spawn handler requires a PHPProcessManager.
* `UniversalPHP` and such are interchangeable with both `BasePHP` and
`WebPHPEndpoint`. This isn't intuitive, especially now that
`WebPHPEndpoint` acts on many PHP instances. Let's make `BasePHP`
distinct from `WebPHPEndpoint`. They will share some methods and props,
but will also have disjoint ones.
@adamziel adamziel moved this to Future work in Playground Board Jul 1, 2024
@adamziel adamziel removed this from the User Experience milestone Nov 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant