8000 Dump container in multiple files · lcobucci/di-builder@a935125 · GitHub
[go: up one dir, main page]

Skip to content

Commit a935125

Browse files
committed
Dump container in multiple files
This option has been added in `symfony/dependency-injection` v4 and the idea is to reduce the amount of files/classes loaded when the container is initialised, thus reducing memory usage and speeding up things. More info: symfony/symfony#23678
1 parent c5285eb commit a935125

File tree

3 files changed

+144
-10
lines changed

3 files changed

+144
-10
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
- mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{.disabled,}
5656
- if [[ ! $(php -m | grep -si xdebug) ]]; then echo "xdebug required for mutation"; exit 1; fi
5757
script:
58-
- ./vendor/bin/infection -s --min-msi=88 --min-covered-msi=100
58+
- ./vendor/bin/infection -s --min-msi=95 --min-covered-msi=95 --threads=4
5959

6060
- stage: Quality
6161
env: STATIC_ANALYSIS=1

src/Compiler.php

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
namespace Lcobucci\DependencyInjection;
55

66
use Lcobucci\DependencyInjection\Config\ContainerConfiguration;
7+
use RuntimeException;
78
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
89
use Symfony\Component\Config\ConfigCache;
910
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1011
use Symfony\Component\DependencyInjection\ContainerBuilder as SymfonyBuilder;
11-
use Symfony\Component\DependencyInjection\Dumper\DumperInterface;
1212
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
13+
use Symfony\Component\Filesystem\Filesystem;
14+
use function array_pop;
1315
use function assert;
1416
use function class_exists;
17+
use function dirname;
1518
use function is_array;
1619

1720
final class Compiler
@@ -64,24 +67,66 @@ private function configurePassList(
6467
}
6568
}
6669

70+
/**
71+
* @throws RuntimeException
72+
*/
6773
private function updateDump(
6874
SymfonyBuilder $container,
6975
ContainerConfiguration $config,
7076
ConfigCache $dump
7177
): void {
7278
$container->compile();
7379

74-
$options = $config->getDumpOptions();
75-
$options['file'] = $dump->getPath();
76-
$options['debug'] = $container->getParameter('app.devmode');
77-
78-
$dump->write(
79-
$this->getDumper($container)->dump($options),
80-
$container->getResources()
80+
$this->writeToFiles(
81+
$this->getContainerContent($container, $config, $dump),
82+
dirname($dump->getPath()) . '/',
83+
$dump,
84+
$container
8185
);
8286
}
8387

84-
private function getDumper(SymfonyBuilder $container): DumperInterface
88+
/**
89+
* @return string[]
90+
*/
91+
private function getContainerContent(
92+
SymfonyBuilder $container,
93+
ContainerConfiguration $config,
94+
ConfigCache $dump
95+
): array {
96+
$options = $config->getDumpOptions();
97+
$options['file'] = $dump->getPath();
98+
$options['debug'] = $container->getParameter('app.devmode');
99+
$options['as_files'] = true;
100+
101+
$content = $this->getDumper($container)->dump($options);
102+
assert(is_array($content));
103+
104+
return $content;
105+
}
106+
107+
/**
108+
* @param string[] $content
109+
*
110+
* @throws RuntimeException
111+
*/
112+
private function writeToFiles(
113+
array $content,
114+
string $baseDir,
115+
ConfigCache $dump,
116+
SymfonyBuilder $container
117+
): void {
118+
$rootCode = array_pop($content);
119+
120+
$filesystem = new Filesystem();
121+
122+
foreach ($content as $file => $code) {
123+
$filesystem->dumpFile($baseDir . $file, $code);
124+
}
125+
126+
$dump->write($rootCode, $container->getResources());
127+
}
128+
129+
private function getDumper(SymfonyBuilder $container): PhpDumper
85130
{
86131
$dumper = new PhpDumper($container);
87132

test/CompilerTest.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Lcobucci\DependencyInjection;
5+
6+
use Generator;
7+
use Lcobucci\DependencyInjection\Compiler\ParameterBag;
8+
use Lcobucci\DependencyInjection\Config\ContainerConfiguration;
9+
use Lcobucci\DependencyInjection\Generators\Yaml;
10+
use org\bovigo\vfs\vfsStream;
11+
use org\bovigo\vfs\vfsStreamDirectory;
12+
use org\bovigo\vfs\vfsStreamFile;
13+
use PHPUnit\Framework\TestCase;
14+
use Symfony\Component\Config\ConfigCache;
15+
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
16+
use function assert;
17+
use function count;
18+
use function iterator_to_array;
19+
use function umask;
20+
21+
final class CompilerTest extends TestCase
22+
{
23+
/**
24+
* @test
25+
*
26+
* @covers \Lcobucci\DependencyInjection\Compiler
27+
*
28+
* @uses \Lcobucci\DependencyInjection\Compiler\ParameterBag
29+
* @uses \Lcobucci\DependencyInjection\Config\ContainerConfiguration
30+
* @uses \Lcobucci\DependencyInjection\Generator
31+
* @uses \Lcobucci\DependencyInjection\Generators\Yaml
32+
*/
33+
public function compileShouldCreateMultipleFiles(): void
34+
{
35+
$root = vfsStream::setup(
36+
'tests',
37+
null,
38+
['services.yml' => 'services: { testing: { class: stdClass, public: true } }']
39+
);
40+
41+
$config = new ContainerConfiguration(
42+
[vfsStream::url('tests/services.yml')],
43+
[
44+
[new ParameterBag(['app.devmode' => true]), PassConfig::TYPE_BEFORE_OPTIMIZATION],
45+
]
46+
);
47+
48+
$dump = new ConfigCache(vfsStream::url('tests/container.php'), false);
49+
50+
$compiler = new Compiler();
51+
$compiler->compile($config, $dump, new Yaml());
52+
53+
$expectedFiles = [
54+
'removed-ids.php',
55+
'getTestingService.php',
56+
$config->getClassName() . '.php',
57+
'container.php',
58+
'container.php.meta',
59+
];
60+
61+
$expectedPermissions = 0666 & ~umask();
62+
$generatedFiles = iterator_to_array($this->getGeneratedFiles($root));
63+
64+
self::assertCount(count($expectedFiles), $generatedFiles);
65+
66+
foreach ($generatedFiles as $name => $file) {
67+
assert($file instanceof vfsStreamFile);
68+
69+
self::assertContains($name, $expectedFiles);
70+
self::assertSame($expectedPermissions, $file->getPermissions());
71+
}
72+
}
73+
74+
private function getGeneratedFiles(vfsStreamDirectory $directory): Generator
75+
{
76+
foreach ($directory->getChildren() as $child) {
77+
if ($child instanceof vfsStreamFile && $child->getName() !== 'services.yml') {
78+
yield $child->getName() => $child;
79+
continue;
80+
}
81+
82+
if (! ($child instanceof vfsStreamDirectory)) {
83+
continue;
84+
}
85+
86+
yield from $this->getGeneratedFiles($child);
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)
0