8000 [DI] generate preload.php file for PHP 7.4 in cache folder · symfony/symfony@aa39efe · GitHub
[go: up one dir, main page]

Skip to content

Commit aa39efe

Browse files
[DI] generate preload.php file for PHP 7.4 in cache folder
1 parent 7cf3fb4 commit aa39efe

File tree

2 files changed

+49
-19
lines changed

2 files changed

+49
-19
lines changed

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class PhpDumper extends Dumper
8181
private $locatedIds = [];
8282
private $serviceLocatorTag;
8383
private $exportedVariables = [];
84+
private $baseClass;
8485

8586
/**
8687
* @var ProxyDumper
@@ -148,11 +149,11 @@ public function dump(array $options = [])
148149

149150
if (0 !== strpos($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) {
150151
$baseClass = sprintf('%s\%s', $options['namespace'] ? '\\'.$options['namespace'] : '', $baseClass);
151-
$baseClassWithNamespace = $baseClass;
152+
$this->baseClass = $baseClass;
152153
} elseif ('Container' === $baseClass) {
153-
$baseClassWithNamespace = Container::class;
154+
$this->baseClass = Container::class;
154155
} else {
155-
$baseClassWithNamespace = $baseClass;
156+
$this->baseClass = $baseClass;
156157
}
157158

158159
$this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
@@ -216,7 +217,7 @@ public function dump(array $options = [])
216217
}
217218

218219
$code =
219-
$this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
220+
$this->startClass($options['class'], $baseClass, $preload).
220221
$this->addServices($services).
221222
$this->addDeprecatedAliases().
222223
$this->addDefaultParametersMethod()
@@ -277,6 +278,30 @@ public function dump(array $options = [])
277278
$time = $options['build_time'];
278279
$id = hash('crc32', $hash.$time);
279280

281+
if ($preload) {
282+
$code[$options['class'].'.preload.php'] = <<<EOF
283+
<?php
284+
285+
// This file has been auto-generated by the Symfony Dependency Injection Component
286+
// You can reference it in the "opcache.preload" php.ini setting on PHP >= 7.4 when preloading is desired
287+
288+
require dirname(__DIR__, 3).'/vendor/autoload.php';
289+
require __DIR__.'/Container{$hash}/{$options['class']}.php';
290+
291+
292+
EOF;
293+
294+
foreach ($preload as $file) {
295+
$file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', 'dirname(__DIR__, $1)', $file);
296+
297+
// Using opcache_compile_file() works, but yields "Can't preload unlinked class [...]" warnings. Why?
298+
// Using require_once instead fails with "Error Shared memory lock not obtained". Why?
299+
// Run this command in a skeleton app to give it a try:
300+
// bin/console c:c && php -dopcache.preload=var/cache/dev/srcApp_KernelDevDebugContainer.preload.php -S localhost:8000 -ddisplay_errors=1 -ddisplay_startup_errors=1
301+
$code[$options['class'].'.preload.php'] .= sprintf("opcache_compile_file(%s);\n", $file);
302+
}
303+
}
304+
280305
$code[$options['class'].'.php'] = <<<EOF
281306
<?php
282307
{$namespaceLine}
@@ -399,7 +424,7 @@ private function collectLineage($class, array &$lineage)
399424
if (!$r = $this->container->getReflectionClass($class, false)) {
400425
return;
401426
}
402-
if ($this->container instanceof $class) {
427+
if (is_a($class, $this->baseClass, true)) {
403428
return;
404429
}
405430
$file = $r->getFileName();
@@ -474,13 +499,16 @@ private function addServiceInclude(string $cId, Definition $definition): string
474499
}
475500

476501
foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
502+
$file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file);
477503
$code .= sprintf(" include_once %s;\n", $file);
478504
}
479505
}
480506

481507
foreach ($this->inlinedDefinitions as $def) {
482508
if ($file = $def->getFile()) {
483-
$code .= sprintf(" include_once %s;\n", $this->dumpValue($file));
509+
$file = $this->dumpValue($file);
510+
$file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file);
511+
$code .= sprintf(" include_once %s;\n", $file);
484512
}
485513
}
486514

@@ -958,7 +986,7 @@ private function addNewInstance(Definition $definition, string $return = '', str
958986
return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail;
959987
}
960988

961-
private function startClass(string $class, string $baseClass, string $baseClassWithNamespace): string
989+
private function startClass(string $class, string $baseClass, ?array &$preload): string
962990
{
963991
$namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
964992

@@ -1005,8 +1033,8 @@ public function __construct()
10051033
$code .= " \$this->containerDir = \$containerDir;\n";
10061034
}
10071035

1008-
if (Container::class !== $baseClassWithNamespace) {
1009-
$r = $this->container->getReflectionClass($baseClassWithNamespace, false);
1036+
if (Container::class !== $this->baseClass) {
1037+
$r = $this->container->getReflectionClass($this->baseClass, false);
10101038
if (null !== $r
10111039
&& (null !== $constructor = $r->getConstructor())
10121040
&& 0 === $constructor->getNumberOfRequiredParameters()
@@ -1026,7 +1054,7 @@ public function __construct()
10261054
$code .= $this->addMethodMap();
10271055
$code .= $this->asFiles ? $this->addFileMap() : '';
10281056
$code .= $this->addAliases();
1029-
$code .= $this->addInlineRequires();
1057+
$code .= $this->addInlineRequires($preload);
10301058
$code .= <<<EOF
10311059
}
10321060
@@ -1227,7 +1255,7 @@ protected function {$methodNameAlias}()
12271255
return $code;
12281256
}
12291257

1230-
private function addInlineRequires(): string
1258+
private function addInlineRequires(?array &$preload): string
12311259
{
12321260
if (!$this->hotPathTag || !$this->inlineRequires) {
12331261
return '';
@@ -1251,11 +1279,13 @@ private function addInlineRequires(): string
12511279
foreach ($lineage as $file) {
12521280
if (!isset($this->inlinedRequires[$file])) {
12531281
$this->inlinedRequires[$file] = true;
1282+
$preload[] = $file;
1283+
$file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file);
12541284
$code .= sprintf("\n include_once %s;", $file);
12551285
}
12561286
}
12571287

1258-
return $code ? sprintf("\n \$this->privates['service_container'] = function () {%s\n };\n", $code) : '';
1288+
return $code ? sprintf("\n \$this->privates['service_container'] = static function () {%s\n };\n", $code) : '';
12591289
}
12601290

12611291
private function addDefaultParametersMethod(): string

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_inline_requires.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ public function __construct()
3636

3737
$this->aliases = [];
3838

39-
$this->privates['service_container'] = function () {
40-
include_once $this->targetDirs[1].'/includes/HotPath/I1.php';
41-
include_once $this->targetDirs[1].'/includes/HotPath/P1.php';
42-
include_once $this->targetDirs[1].'/includes/HotPath/T1.php';
43-
include_once $this->targetDirs[1].'/includes/HotPath/C1.php';
39+
$this->privates['service_container'] = static function () {
40+
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/I1.php';
41+
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/P1.php';
42+
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/T1.php';
43+
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/C1.php';
4444
};
4545
}
4646

@@ -90,8 +90,8 @@ protected function getC1Service()
9090
*/
9191
protected function getC2Service()
9292
{
93-
include_once $this->targetDirs[1].'/includes/HotPath/C2.php';
94-
include_once $this->targetDirs[1].'/includes/HotPath/C3.php';
93+
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/C2.php';
94+
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/C3.php';
9595

9696
return $this->services['Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C2'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2(new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3());
9797
}

0 commit comments

Comments
 (0)
0