Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2bd4ffb

Browse files
[DI] Improve performance of removing/inlining passes
1 parent8bbd738 commit2bd4ffb

12 files changed

+230
-121
lines changed

‎src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
useSymfony\Component\DependencyInjection\ContainerBuilder;
1616
useSymfony\Component\DependencyInjection\Definition;
1717
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
18+
useSymfony\Component\DependencyInjection\ExpressionLanguage;
1819
useSymfony\Component\DependencyInjection\Reference;
20+
useSymfony\Component\ExpressionLanguage\Expression;
1921

2022
/**
2123
* @author Nicolas Grekas <p@tchwork.com>
@@ -28,6 +30,9 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
2830
protected$container;
2931
protected$currentId;
3032

33+
private$processExpressions =false;
34+
private$expressionLanguage;
35+
3136
/**
3237
* {@inheritdoc}
3338
*/
@@ -42,6 +47,11 @@ public function process(ContainerBuilder $container)
4247
}
4348
}
4449

50+
protectedfunctionenableExpressionProcessing()
51+
{
52+
$this->processExpressions =true;
53+
}
54+
4555
/**
4656
* Processes a value found in a definition tree.
4757
*
@@ -63,6 +73,8 @@ protected function processValue($value, $isRoot = false)
6373
}
6474
}elseif ($valueinstanceof ArgumentInterface) {
6575
$value->setValues($this->processValue($value->getValues()));
76+
}elseif ($valueinstanceof Expression &&$this->processExpressions) {
77+
$this->getExpressionLanguage()->compile((string)$value,array('this' =>'container'));
6678
}elseif ($valueinstanceof Definition) {
6779
$value->setArguments($this->processValue($value->getArguments()));
6880
$value->setProperties($this->processValue($value->getProperties()));
@@ -169,4 +181,25 @@ protected function getReflectionMethod(Definition $definition, $method)
169181

170182
return$r;
171183
}
184+
185+
privatefunctiongetExpressionLanguage()
186+
{
187+
if (null ===$this->expressionLanguage) {
188+
if (!class_exists(ExpressionLanguage::class)) {
189+
thrownewRuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
190+
}
191+
192+
$providers =$this->container->getExpressionLanguageProviders();
193+
$this->expressionLanguage =newExpressionLanguage(null,$providers,function ($arg) {
194+
if ('""' ===substr_replace($arg,'',1, -1)) {
195+
$id =stripcslashes(substr($arg,1, -1));
196+
$this->processValue(newReference($id));
197+
}
198+
199+
returnsprintf('$this->get(%s)',$arg);
200+
});
201+
}
202+
203+
return$this->expressionLanguage;
204+
}
172205
}

‎src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php‎

Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
useSymfony\Component\DependencyInjection\Argument\ArgumentInterface;
1515
useSymfony\Component\DependencyInjection\ContainerInterface;
1616
useSymfony\Component\DependencyInjection\Definition;
17-
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
18-
useSymfony\Component\DependencyInjection\ExpressionLanguage;
1917
useSymfony\Component\DependencyInjection\Reference;
2018
useSymfony\Component\DependencyInjection\ContainerBuilder;
2119
useSymfony\Component\ExpressionLanguage\Expression;
@@ -28,29 +26,33 @@
2826
* retrieve the graph in other passes from the compiler.
2927
*
3028
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
29+
* @author Nicolas Grekas <p@tchwork.com>
3130
*/
3231
class AnalyzeServiceReferencesPassextends AbstractRecursivePassimplements RepeatablePassInterface
3332
{
3433
private$graph;
3534
private$currentDefinition;
3635
private$onlyConstructorArguments;
3736
private$lazy;
38-
private$expressionLanguage;
37+
private$inExpression;
38+
private$definitions;
39+
private$aliases;
3940

4041
/**
4142
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
4243
*/
4344
publicfunction__construct(bool$onlyConstructorArguments =false)
4445
{
4546
$this->onlyConstructorArguments =$onlyConstructorArguments;
47+
$this->enableExpressionProcessing();
4648
}
4749

4850
/**
4951
* {@inheritdoc}
5052
*/
5153
publicfunctionsetRepeatedPass(RepeatedPass$repeatedPass)
5254
{
53-
// no-op for BC
55+
@trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.1.',__METHOD__),E_USER_DEPRECATED);
5456
}
5557

5658
/**
@@ -62,13 +64,19 @@ public function process(ContainerBuilder $container)
6264
$this->graph =$container->getCompiler()->getServiceReferenceGraph();
6365
$this->graph->clear();
6466
$this->lazy =false;
67+
$this->definitions =$container->getDefinitions();
68+
$this->aliases =$container->getAliases();
6569

66-
foreach ($container->getAliases()as$id =>$alias) {
70+
foreach ($this->aliasesas$id =>$alias) {
6771
$targetId =$this->getDefinitionId((string)$alias);
68-
$this->graph->connect($id,$alias,$targetId,$this->getDefinition($targetId),null);
72+
$this->graph->connect($id,$alias,$targetId,null !==$targetId ?$this->container->getDefinition($targetId) :null,null);
6973
}
7074

71-
parent::process($container);
75+
try {
76+
parent::process($container);
77+
}finally {
78+
$this->aliases =$this->definitions =array();
79+
}
7280
}
7381

7482
protectedfunctionprocessValue($value,$isRoot =false)
@@ -83,13 +91,16 @@ protected function processValue($value, $isRoot = false)
8391
return$value;
8492
}
8593
if ($valueinstanceof Expression) {
86-
$this->getExpressionLanguage()->compile((string)$value,array('this' =>'container'));
87-
88-
return$value;
94+
$this->inExpression =true;
95+
try {
96+
returnparent::processValue($value);
97+
}finally {
98+
$this->inExpression =false;
99+
}
89100
}
90101
if ($valueinstanceof Reference) {
91102
$targetId =$this->getDefinitionId((string)$value);
92-
$targetDefinition =$this->getDefinition($targetId);
103+
$targetDefinition =null !==$targetId ?$this->container->getDefinition($targetId) :null;
93104

94105
$this->graph->connect(
95106
$this->currentId,
@@ -101,6 +112,19 @@ protected function processValue($value, $isRoot = false)
101112
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE ===$value->getInvalidBehavior()
102113
);
103114

115+
if ($this->inExpression) {
116+
$this->inExpression =false;
117+
$this->graph->connect(
118+
'.internal.reference_in_expression',
119+
null,
120+
$targetId,
121+
$targetDefinition,
122+
$value,
123+
$this->lazy || ($targetDefinition &&$targetDefinition->isLazy()),
124+
true
125+
);
126+
}
127+
104128
return$value;
105129
}
106130
if (!$valueinstanceof Definition) {
@@ -127,49 +151,12 @@ protected function processValue($value, $isRoot = false)
127151
return$value;
128152
}
129153

130-
privatefunctiongetDefinition(?string$id): ?Definition
131-
{
132-
returnnull ===$id ?null :$this->container->getDefinition($id);
133-
}
134-
135154
privatefunctiongetDefinitionId(string$id): ?string
136155
{
137-
while ($this->container->hasAlias($id)) {
138-
$id = (string)$this->container->getAlias($id);
139-
}
140-
141-
if (!$this->container->hasDefinition($id)) {
142-
returnnull;
143-
}
144-
145-
return$id;
146-
}
147-
148-
privatefunctiongetExpressionLanguage()
149-
{
150-
if (null ===$this->expressionLanguage) {
151-
if (!class_exists(ExpressionLanguage::class)) {
152-
thrownewRuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
153-
}
154-
155-
$providers =$this->container->getExpressionLanguageProviders();
156-
$this->expressionLanguage =newExpressionLanguage(null,$providers,function ($arg) {
157-
if ('""' ===substr_replace($arg,'',1, -1)) {
158-
$id =stripcslashes(substr($arg,1, -1));
159-
$id =$this->getDefinitionId($id);
160-
161-
$this->graph->connect(
162-
$this->currentId,
163-
$this->currentDefinition,
164-
$id,
165-
$this->getDefinition($id)
166-
);
167-
}
168-
169-
returnsprintf('$this->get(%s)',$arg);
170-
});
156+
while (isset($this->aliases[$id])) {
157+
$id = (string)$this->aliases[$id];
171158
}
172159

173-
return$this->expressionLanguage;
160+
returnisset($this->definitions[$id]) ?$id :null;
174161
}
175162
}

‎src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php‎

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespaceSymfony\Component\DependencyInjection\Compiler;
1313

1414
useSymfony\Component\DependencyInjection\Argument\ArgumentInterface;
15+
useSymfony\Component\DependencyInjection\ContainerBuilder;
1516
useSymfony\Component\DependencyInjection\Definition;
1617
useSymfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
1718
useSymfony\Component\DependencyInjection\Reference;
@@ -23,14 +24,78 @@
2324
*/
2425
class InlineServiceDefinitionsPassextends AbstractRecursivePassimplements RepeatablePassInterface
2526
{
27+
private$analyzingPass;
28+
private$repeatedPass;
2629
private$cloningIds =array();
30+
private$connectedIds =array();
31+
private$notInlinedIds =array();
32+
private$inlinedIds =array();
33+
private$graph;
34+
35+
publicfunction__construct(AnalyzeServiceReferencesPass$analyzingPass =null)
36+
{
37+
$this->analyzingPass =$analyzingPass;
38+
}
2739

2840
/**
2941
* {@inheritdoc}
3042
*/
3143
publicfunctionsetRepeatedPass(RepeatedPass$repeatedPass)
3244
{
33-
// no-op for BC
45+
@trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.1.',__METHOD__),E_USER_DEPRECATED);
46+
$this->repeatedPass =$repeatedPass;
47+
}
48+
49+
publicfunctionprocess(ContainerBuilder$container)
50+
{
51+
$this->container =$container;
52+
if ($this->analyzingPass) {
53+
$analyzedContainer =newContainerBuilder();
54+
$analyzedContainer->setAliases($container->getAliases());
55+
$analyzedContainer->setDefinitions($container->getDefinitions());
56+
}else {
57+
$analyzedContainer =$container;
58+
}
59+
try {
60+
$this->connectedIds =$this->notInlinedIds =$container->getDefinitions();
61+
do {
62+
if ($this->analyzingPass) {
63+
$analyzedContainer->setDefinitions(array_intersect_key($analyzedContainer->getDefinitions(),$this->connectedIds));
64+
$this->analyzingPass->process($analyzedContainer);
65+
}
66+
$this->graph =$analyzedContainer->getCompiler()->getServiceReferenceGraph();
67+
$notInlinedIds =$this->notInlinedIds;
68+
$this->connectedIds =$this->notInlinedIds =$this->inlinedIds =array();
69+
70+
foreach ($analyzedContainer->getDefinitions()as$id =>$definition) {
71+
if (!$this->graph->hasNode($id)) {
72+
continue;
73+
}
74+
foreach ($this->graph->getNode($id)->getOutEdges()as$edge) {
75+
if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) {
76+
$this->currentId =$id;
77+
$this->processValue($definition,true);
78+
break;
79+
}
80+
}
81+
}
82+
83+
foreach ($this->inlinedIdsas$id =>$isPublic) {
84+
if (!$isPublic) {
85+
$container->removeDefinition($id);
86+
$analyzedContainer->removeDefinition($id);
87+
}
88+
}
89+
}while ($this->inlinedIds &&$this->analyzingPass);
90+
91+
if ($this->inlinedIds &&$this->repeatedPass) {
92+
$this->repeatedPass->setRepeat();
93+
}
94+
}finally {
95+
$this->container =null;
96+
$this->connectedIds =$this->notInlinedIds =$this->inlinedIds =array();
97+
$this->graph =null;
98+
}
3499
}
35100

36101
/**
@@ -50,17 +115,21 @@ protected function processValue($value, $isRoot = false)
50115
$value =clone$value;
51116
}
52117

53-
if (!$valueinstanceof Reference || !$this->container->hasDefinition($id = (string)$value)) {
118+
if (!$valueinstanceof Reference) {
54119
returnparent::processValue($value,$isRoot);
120+
}elseif (!$this->container->hasDefinition($id = (string)$value)) {
121+
return$value;
55122
}
56123

57124
$definition =$this->container->getDefinition($id);
58125

59-
if (!$this->isInlineableDefinition($id,$definition,$this->container->getCompiler()->getServiceReferenceGraph())) {
126+
if (!$this->isInlineableDefinition($id,$definition)) {
60127
return$value;
61128
}
62129

63130
$this->container->log($this,sprintf('Inlined service "%s" to "%s".',$id,$this->currentId));
131+
$this->inlinedIds[$id] =$definition->isPublic();
132+
$this->notInlinedIds[$this->currentId] =true;
64133

65134
if ($definition->isShared()) {
66135
return$definition;
@@ -86,7 +155,7 @@ protected function processValue($value, $isRoot = false)
86155
*
87156
* @return bool If the definition is inlineable
88157
*/
89-
privatefunctionisInlineableDefinition($id,Definition$definition,ServiceReferenceGraph$graph)
158+
privatefunctionisInlineableDefinition($id,Definition$definition)
90159
{
91160
if ($definition->getErrors() ||$definition->isDeprecated() ||$definition->isLazy() ||$definition->isSynthetic()) {
92161
returnfalse;
@@ -100,30 +169,37 @@ private function isInlineableDefinition($id, Definition $definition, ServiceRefe
100169
returnfalse;
101170
}
102171

103-
if (!$graph->hasNode($id)) {
172+
if (!$this->graph->hasNode($id)) {
104173
returntrue;
105174
}
106175

107176
if ($this->currentId ==$id) {
108177
returnfalse;
109178
}
179+
$this->connectedIds[$id] =true;
110180

111-
$ids =array();
112-
foreach ($graph->getNode($id)->getInEdges()as$edge) {
181+
$srcIds =array();
182+
$srcIdsCount =0;
183+
foreach ($this->graph->getNode($id)->getInEdges()as$edge) {
184+
$srcId =$edge->getSourceNode()->getId();
185+
$this->connectedIds[$srcId] =true;
113186
if ($edge->isWeak()) {
114187
returnfalse;
115188
}
116-
$ids[] =$edge->getSourceNode()->getId();
189+
$srcIds[$srcId] =true;
190+
++$srcIdsCount;
117191
}
118192

119-
if (count(array_unique($ids)) >1) {
193+
if (1 !==\count($srcIds)) {
194+
$this->notInlinedIds[$id] =true;
195+
120196
returnfalse;
121197
}
122198

123-
if (count($ids) >1 &&is_array($factory =$definition->getFactory()) && ($factory[0]instanceof Reference ||$factory[0]instanceof Definition)) {
199+
if ($srcIdsCount >1 &&is_array($factory =$definition->getFactory()) && ($factory[0]instanceof Reference ||$factory[0]instanceof Definition)) {
124200
returnfalse;
125201
}
126202

127-
return!$ids ||$this->container->getDefinition($ids[0])->isShared();
203+
return$this->container->getDefinition($srcId)->isShared();
128204
}
129205
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp