-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DI] generate preload.php file for PHP 7.4 in cache folder #32032
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
Conversation
src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_inline_requires.php
Show resolved
Hide resolved
src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_inline_requires.php
Show resolved
Hide resolved
85e1fec
to
e2b7dce
Compare
For reference, here is some previous work by @BenMorel that shows that loading only the hot classes (vs everything) is what provides the best boost. Identifying these hot classes is what I'm trying to achieve here. |
Is it really worth it to preload only hot classes? Doesn't that increase the complexity a lot, vs just preloading everything? |
There's a slight performance improvement vs preloading everything when preloading hot classes that were selected using actual runtime data, as reported by opcache after a few runs of the application:
(original benchmark in this thread) Any other pre-computed list would need to be benchmarked again, as the results may be very different (and could even be slower than preloading everything, as the list may be missing classes that will need to be linked at runtime). All in all, the difference between a carefully optimized preloader and an eager preloader is small, I'd personally be in favour of preloading everything by default, and let users create their own preloading script if they need the extra few % of performance. What could be interesting however, is shipping Symfony with a tool (like the one I used in this post) to generate the preloading file from opcache, together with some instructions on how to:
|
Identifying the hot classes using runtime data from opcache has a big drawback: rebooting the fpm pool on prod servers. Not sure it's calling for good ops practices. |
I did not have in mind to gather runtime data from the prod environment, but from the dev one! No worries, I just wanted to give a bit of warning here, I'm looking forward to your numbers! |
aa39efe
to
8aa4aca
Compare
I am not sure, if this is the right place to ask. In the related RFC they say:
How do you plan to manage updates in the |
Preloading is fundamentally incompatible with shared hosting yes, so you wouldn't use this on your provider. The added file is totally opt-in so one won't use it if one isn't able to restart the FPM server when deploying new code, that's correct. |
Nope, preloading requires setup at server level ( Most likely any preloading script shipped with Symfony or Composer will be opt-in, and the choice to include it or not will be left to the server administrator. |
It's 2019, so hopefully the population of developers who unfortunately still have to deal with shared hosting is shrinking rapidly... |
…grekas)" (nicolas-grekas) This PR was merged into the 4.4 branch. Discussion ---------- Revert "minor #32054 Prepare for PHP 7.4 preload (nicolas-grekas)" | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #32032 | License | MIT | Doc PR | - This reverts commit a0aa941, reversing changes made to 8496003. This change is incompatible with Composer's class map generation. Commits ------- 8a1813a Revert "minor #32054 Prepare for PHP 7.4 preload (nicolas-grekas)"
Hi @nicolas-grekas, if we have this feature in composer we could configure the classes directly on HttpFoundation composer.json file: {
"preload": [
"Symfony\\HttpFoundation\\{Request,Response}",
"Symfony\\EntireNamespace\\*",
"Symfony\\{NS1,NS2}\\*"
]
} |
I've just read the RFC at composer/composer#7777 and seems that is not an easy decision to put such feature on composer. |
517bd3e
to
5d119d6
Compare
5d119d6
to
c4dad0d
Compare
I rebased this PR and I think it's time to merge it. Preloading doesn't work yet, but that's on PHP's side. Status: needs review |
Thank you @nicolas-grekas. |
…lder (nicolas-grekas) This PR was merged into the 4.4 branch. Discussion ---------- [DI] generate preload.php file for PHP 7.4 in cache folder | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #29105 | License | MIT | Doc PR | - This PR makes the PhpDumper generate a preloading file suited for PHP 7.4. On a skeleton app, the generated file is `var/cache/dev/srcApp_KernelDevDebugContainer.preload.php` (of course, this varies by env name + kernel class) One missing thing is listing some classes that are always needed but are not related to services. Typically: `Request` and `Response`. We might need a new mechanism to make this list extensible. I did not measure the benefit of this on PHP 7.4. I would really appreciate if someone could give it a try on PHP 7.4 with preloading enabled. Commits ------- c4dad0d [DI] generate preload.php file for PHP 7.4 in cache folder
@@ -522,13 +553,17 @@ private function addServiceInclude(string $cId, Definition $definition): string | |||
} | |||
|
|||
foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { | |||
$file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file); |
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.
why generating code using $this->targetDirs
first, to replace it later with dirname(__DIR__)
? We would generate the right code directly.
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 prefer not changing this when it's not needed: the code starts with
$this->targetDirs[0] = \dirname($containerDir)
: target dirs are dynamic. This is used when calling cache clear and is stable, no reason to change.
Using dirname()
is really useful when referencing files in the src/
or in the vendor/
folder, which is where it is used.
Lowest risk strategy :)
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.
Second look, I did something, please check #33529 :)
@@ -1285,7 +1320,7 @@ protected function {$methodNameAlias}() | |||
return $code; | |||
} | |||
|
|||
private function addInlineRequires(): string | |||
private function addInlineRequires(?array &$preload): string |
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.
should null
be allowed ?
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.
to allow calling the method with an uninitialized variable
$c = $p->getDefaultValueConstantName(); | ||
|
||
if ($i = strpos($c, '::')) { | ||
self::doPreload(substr($c, 0, $i)); |
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.
if you reuse the same class multiple types in different parameters, wouldn't this preload it multiple times ? Also, it would not register it in $preloaded
in the main function, and so it will be processed once again by the main function.
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.
Indeed, fixed in #33525
@nicolas-grekas As soon as PHP 7.4 will be available, I will benchmark with and without preloading and add results on phpbenchmarks.com ;) |
@steevanb Is there a benchmark on preloading per your note above? I looked on the site and didn't find anything specific, but maybe I just missed it. |
@bradjones1 for now PHP 7.4 is not added on phpbenchmarks.com, cause i'm on a new version of benchmarks and site who will be released in a few weeks. |
This PR makes the PhpDumper generate a preloading file suited for PHP 7.4.
On a skeleton app, the generated file is
var/cache/dev/srcApp_KernelDevDebugContainer.preload.php
(of course, this varies by env name + kernel class)One missing thing is listing some classes that are always needed but are not related to services.
Typically:
Request
andResponse
. We might need a new mechanism to make this list extensible.I did not measure the benefit of this on PHP 7.4. I would really appreciate if someone could give it a try on PHP 7.4 with preloading enabled.