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

Skip to content

Optimize ReplaceAliasByActualDefinitionPass #18265

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

Merged
merged 1 commit into from
Mar 31, 2016
Merged

Optimize ReplaceAliasByActualDefinitionPass #18265

merged 1 commit into from
Mar 31, 2016

Conversation

ajb-in
Copy link
Contributor

@ajb-in ajb-in commented Mar 22, 2016

Q A
Branch? 2.3
Bug fix? yes (performance)
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets -
License MIT
Doc PR -

Previous implementation passed over every definition for every alias (n*m runtime).
New implementation passes once over all aliases and once over all definitions (n+m).
Also removing needless "restart" logic.

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 22, 2016

Note: patch applies to master with minor modification (tested).

@lstrojny
Copy link
Contributor

Improves container dump times from ~40s to ~16s in real world applications.

}

return $arguments;
}

private function updateFactoryServiceReference($factoryService, $currentId, $newId)
private function updateFactoryReferenceId($replacements, $referenceId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about adding a doc block here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On it 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@GuilhemN
Copy link
Contributor

This looks great 👍
Thank you @ajb-in 😄

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 22, 2016

Thanks @Ener-Getick ^_^

$aliasId = (string) $alias;

if (isset($replacements[$aliasId])) {
$container->setAlias($defId, $replacements[$aliasId]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must respect the visibility of the existing alias (allowing it to be removed in case of a private alias not being referenced anywhere anymore after other optimizations)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to stick to the original behaviour, namely: remove the definition of the target, point the alias to the definition, and point every subsequent alias with the same target to the first alias.

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 23, 2016

@stof re chains: I played with the existing testcase for 2.3 to see what happens with chained aliases. I ran this code:

    $container = new ContainerBuilder();

    $aDefinition = $container->register('a', '\stdClass');
    $aDefinition->setFactory(array(new Reference('b'), 'createA'));

    $bDefinition = new Definition('\stdClass');
    $bDefinition->setPublic(false);
    $container->setDefinition('b', $bDefinition);

    $container->setAlias('a_alias', 'a');
    $container->setAlias('b_alias', 'b');

    // I added these three lines:
    $container->setAlias('c_alias', 'b');
    $container->setAlias('d_alias', 'c_alias');
    $container->setAlias('e_alias', 'd_alias');

    $this->process($container);

and it 'sploded on 2.3:

There was 1 error:
1) Symfony\Component\DependencyInjection\Tests\Compiler\ReplaceAliasByActualDefinitionPassTest::testProcess
Symfony\Component\DependencyInjection\Exception\InvalidArgumentException: Unable to replace alias "d_alias" with actual definition "c_alias".
/code/symfony/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php:48
/code/symfony/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php:63
/code/symfony/src/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php:69
/code/symfony/src/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php:40
Caused by
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "c_alias".

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 23, 2016

It explodes also if I change the extra part to this:

    // I added these two lines:
    $container->setAlias('c_alias', 'b_alias');
    $container->setAlias('d_alias', 'c_alias');

@tadcka
Copy link
Contributor

tadcka commented Mar 23, 2016

👍

@egils
Copy link

egils commented Mar 23, 2016

Lovely! 👍

@xabbuh
Copy link
Member

xabbuh commented Mar 25, 2016

@ajb-in Aliases that refer to other aliases should have been resolved in the ResolveReferencesToAliasesPass which is run before the ReplaceAliasByActualDefinitionPass.

*
* @return string
*/
private function updateFactoryReferenceId($replacements, $referenceId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing typehint array for $replacements

@Tobion
Copy link
Contributor

Tobion commented Mar 27, 2016

👍 apart from those small doc fixes.


$seenAliasTargets = array();
$replacements = array();
foreach ($container->getAliases() as $definitionID => $target) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be $definitionId as $targetId is used later

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id is upper-cased (ID instead of Id), i think it should be changed for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see, true

} catch (InvalidArgumentException $e) {
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $id, $alias), null, $e);
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionID, $target), null, $e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not using $targetId here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea :3 That's what the old code was doing though (using $alias instead of $aliasId). I'll change it.

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 27, 2016

@Tobion @Ener-Getick Did doc and variable name fixes; looks better?

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 27, 2016

@xabbuh @stof Then this pass doesn't need to be concerned with chains whatsoever, right?

@fabpot
Copy link
Member

fabpot commented Mar 27, 2016

As this is not a bug fix, it should be merged in master, not 2.3

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 27, 2016

@fabpot When I asked in #symfony I was told that it could count as a performance bug, so that's why I went with 2.3; @javiereguiluz seemed to agree since he labeled this PR as 'bug'.
I'll rebase it onto master if needed, of course.

@fabpot
Copy link
Member

fabpot commented Mar 27, 2016

Sorry about the confusion. It's true that we've been more willing to merge PRs that do not strictly fix bugs in maintained branches (and I probably merged some myself), but I think this is a mistake. First, we want old branches to be as stable as possible, and merging non-bug fixes can introduce subtle regressions (happened in the past). Then, improving performance in new versions is a great incentive for people to upgrade, which is always a good idea.

/cc @symfony/deciders

@Tobion
Copy link
Contributor

Tobion commented Mar 28, 2016

I'd prefer to merge refactorings like this one in maitainance branches as it will make maintaining branches easier when they are more similar and do not diverge that much just because of refactorings.

@Tobion
Copy link
Contributor

Tobion commented Mar 28, 2016

And introducing suble behavior changes should not be an argument. It just means we do not have enough tests (or it's really an edge case that wasn't meant to be like this). E.g. the refactoring in the templating parser actually revealed that people use absolute paths that wasn't intended that way.

@fabpot
Copy link
Member

fabpot commented Mar 30, 2016

@ajb-in Can you rebase on current 2.3? Thanks.

@weaverryan
Copy link
Member

In general, I'd prefer things like this to be merged into master. If this causes a subtle behavior change that isn't caught by our tests, that should be our problem, not a problem that is discovered by users in a patch update. We need users to have very high confidence in upgrading patch versions (otherwise, they may stay on insecure versions!)

But it's not black and white - a performance issue could be a bug, so we can do anything here.

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 31, 2016

Rebased on latest 2.3; also squashed, added a comment, and added a plug to this review on the commit message :3

@fabpot
Copy link
Member

fabpot commented Mar 31, 2016

@ajb-in Can you remove the reference in the commit message? We already have everything in place to automatically get that in Git notes.

@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 31, 2016

@fabpot Done; just wanted to give some due credit :3

@fabpot
Copy link
Member

fabpot commented Mar 31, 2016

Tests are broken apparently.

Previous implementation passed over every alias and every definition, for every
alias (n*(n+m) runtime). New implementation passes once over all aliases and
once over all definitions (n+m).

Also removing needless "restart" logic --- it has no real effect in either case.
@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 31, 2016

@fabpot I forgot to rename a variable =P
Fixed it now

@fabpot
Copy link
Member

fabpot commented Mar 31, 2016

Thank you @ajb-in.

@fabpot fabpot merged commit ab8dc0c into symfony:2.3 Mar 31, 2016
fabpot added a commit that referenced this pull request Mar 31, 2016
This PR was merged into the 2.3 branch.

Discussion
----------

Optimize ReplaceAliasByActualDefinitionPass

| Q             | A
| ------------- | ---
| Branch?       | 2.3
| Bug fix?      | yes (performance)
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Previous implementation passed over every definition for every alias (n*m runtime).
New implementation passes once over all aliases and once over all definitions (n+m).
Also removing needless "restart" logic.

Commits
-------

ab8dc0c Optimize ReplaceAliasByActualDefinitionPass
@ajb-in
Copy link
Contributor Author

ajb-in commented Mar 31, 2016

🍻 Thanks to everyone!

solivier pushed a commit to solivier/FOSElasticaBundle that referenced this pull request May 18, 2016
* Test were broken because of this PR introduced in symfony 2.3:
symfony/symfony#18265

* We were passing an object instead of a string.
solivier added a commit to solivier/FOSElasticaBundle that referenced this pull request May 18, 2016
* Tests were broken because of this PR introduced in symfony 2.3:
symfony/symfony#18265

* We were passing an object instead of a string.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.