Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d077e62

Browse files
committed
Optimize circular collection by removing flattening
1 parent be8fd56 commit d077e62

File tree

4 files changed

+40
-63
lines changed

4 files changed

+40
-63
lines changed

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

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -406,48 +406,22 @@ private function analyzeReferences()
406406
$this->singleUsePrivateIds[$id] = $id;
407407
}
408408

409-
$newNodes = [];
410-
if (!$this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes, $newNodes)) {
411-
foreach ($newNodes as $newNodeId => $_) {
412-
$checkedNodes[$newNodeId] = [];
413-
}
414-
continue;
415-
}
416-
417-
$nodesToFlatten = $newNodes;
418-
do {
419-
$changedNodes = [];
420-
foreach ($nodesToFlatten as $newNodeId => $_) {
421-
$deps = &$checkedNodes[$newNodeId];
422-
foreach ($deps as $id => [$path, $depsByConstructor]) {
423-
foreach ($checkedNodes[$id] as $depsId => [$subPath, $subDepsByConstructor]) {
424-
if (!isset($deps[$depsId]) || ($depsByConstructor && $subDepsByConstructor && !$deps[$depsId][1])) {
425-
array_unshift($subPath, $id);
426-
$deps[$depsId] = [$subPath, $depsByConstructor && $subDepsByConstructor];
427-
$changedNodes += $newNodes[$newNodeId] ?? [];
428-
}
429-
}
430-
}
431-
}
432-
} while ($nodesToFlatten = $changedNodes);
433-
434-
foreach ($newNodes as $newNodeId => $_) {
435-
if (null !== $n = $checkedNodes[$newNodeId][$newNodeId] ?? null) {
436-
$this->addCircularReferences($newNodeId, $n[0], $n[1]);
437-
}
409+
$circular = $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes);
410+
foreach ($circular as [$loop, $byConstructor]) {
411+
$sourceId = array_shift($loop);
412+
$this->addCircularReferences($sourceId, $loop, $byConstructor);
438413
}
439414
}
440415

441416
$this->container->getCompiler()->getServiceReferenceGraph()->clear();
442417
$this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences);
443418
}
444419

445-
private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$newNodes, array $path = []): bool
420+
private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array $path = [], bool $byConstructor = true): array
446421
{
447-
$path[$sourceId] = true;
448-
$checkedNodes[$sourceId] = [];
449-
$newNodes[$sourceId] = [];
450-
$circular = false;
422+
$path[$sourceId] = $byConstructor;
423+
$checkedNodes[$sourceId] = true;
424+
$circular = [];
451425
foreach ($edges as $edge) {
452426
$node = $edge->getDestNode();
453427
$id = $node->getId();
@@ -456,14 +430,26 @@ private function collectCircularReferences(string $sourceId, array $edges, array
456430
}
457431

458432
if (isset($path[$id])) {
459-
$circular = true;
433+
$loop = null;
434+
$loopByConstructor = $byConstructor;
435+
foreach ($path as $k => $pathByConstructor) {
436+
if (null !== $loop) {
437+
$loop[] = $k;
438+
$loopByConstructor = $loopByConstructor && $pathByConstructor;
439+
} elseif ($k === $id) {
440+
$loop = [$k];
441+
}
442+
}
443+
if (!isset($circular[$id]) || (!$circular[$id][1] && $loopByConstructor)) {
444+
$circular[$id] = [$loop, $loopByConstructor];
445+
}
460446
} elseif (!isset($checkedNodes[$id])) {
461-
$circular = $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes, $newNodes, $path) || $circular;
462-
}
463-
464-
$checkedNodes[$sourceId][$id] = [[], $edge->isReferencedByConstructor()];
465-
if (isset($newNodes[$id])) {
466-
$newNodes[$id][$sourceId] = true;
447+
$newCircular = $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes, $path, $edge->isReferencedByConstructor());
448+
foreach ($newCircular as $id => [$loop, $byCon]) {
449+
if (!isset($circular[$id]) || (!$circular[$id][1] && $byCon)) {
450+
$circular[$id] = [$loop, $byCon];
451+
}
452+
}
467453
}
468454
}
469455
unset($path[$sourceId]);

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,10 @@ public function testAlmostCircular($visibility)
10701070

10711071
$manager = $container->get('manager');
10721072
$this->assertEquals(new \stdClass(), $manager);
1073+
$subscriber = $container->get('subscriber');
1074+
$this->assertEquals(new \stdClass(), $subscriber);
1075+
$connection = $container->get('connection');
1076+
$this->assertEquals(new \stdClass(), $connection);
10731077

10741078
$manager = $container->get('manager2');
10751079
$this->assertEquals(new \stdClass(), $manager);

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -349,15 +349,13 @@ protected function getManager2Service()
349349
*/
350350
protected function getManager3Service($lazyLoad = true)
351351
{
352-
$a = ($this->services['listener3'] ?? $this->getListener3Service());
352+
$a = new \stdClass();
353353

354-
if (isset($this->services['manager3'])) {
355-
return $this->services['manager3'];
356-
}
357-
$b = new \stdClass();
358-
$b->listener = [0 => $a];
354+
$this->services['manager3'] = $instance = new \stdClass($a);
359355

360-
return $this->services['manager3'] = new \stdClass($b);
356+
$a->listener = [0 => ($this->services['listener3'] ?? $this->getListener3Service())];
357+
358+
return $instance;
361359
}
362360

363361
/**

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

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,11 @@ protected function getBaz6Service()
162162
*/
163163
protected function getConnectionService()
164164
{
165-
$a = ($this->services['dispatcher'] ?? $this->getDispatcherService());
166-
167-
if (isset($this->services['connection'])) {
168-
return $this->services['connection'];
169-
}
170-
$b = new \stdClass();
165+
$a = new \stdClass();
171166

172-
$this->services['connection'] = $instance = new \stdClass($a, $b);
167+
$this->services['connection'] = $instance = new \stdClass(($this->services['dispatcher'] ?? $this->getDispatcherService()), $a);
173168

174-
$b->logger = ($this->services['logger'] ?? $this->getLoggerService());
169+
$a->logger = ($this->services['logger'] ?? $this->getLoggerService());
175170

176171
return $instance;
177172
}
@@ -581,13 +576,7 @@ protected function getRootService()
581576
*/
582577
protected function getSubscriberService()
583578
{
584-
$a = ($this->services['manager'] ?? $this->getManagerService());
585-
586-
if (isset($this->services['subscriber'])) {
587-
return $this->services['subscriber'];
588-
}
589-
590-
return $this->services['subscriber'] = new \stdClass($a);
579+
return $this->services['subscriber'] = new \stdClass(($this->services['manager'] ?? $this->getManagerService()));
591580
}
592581

593582
/**

0 commit comments

Comments
 (0)