8000 [DI] Only rebuild autowiring cache when actually needed by weaverryan · Pull Request #18144 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[DI] Only rebuild autowiring cache when actually needed #18144

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

Closed
wants to merge 5 commits into from

Conversation

weaverryan
Copy link
Member
Q A
Branch master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets none
License MIT
Doc PR n/a

With autowiring, the container is currently rebuilt when an autowired class is modified in any way. That makes it unusable for large systems. However, this doesn't need to be true: we only need to rebuild the cache if a construct argument changes. This adds that change, and it's quite simple

This idea can/should also be adapted easily to the @Route cache (I don't believe it has something "smart" like this).

Thanks!

@weaverryan
Copy link
Member Author

I had an idea: we could make the new resource checker "generic" - something that accepts any class-related information (method + arg info, annotation info, etc). Then it could be used by autowiring, but also by the @Route system in SensioFrameworkExtraBundle. It would then be "fine" to add it as a new, hardcoded resource checker.

@weaverryan weaverryan force-pushed the autowiring_smart_cache branch 2 times, most recently from ea23c0e to 4b521c5 Compare March 27, 2016 17:00
@weaverryan weaverryan changed the title [DI][WIP] Smart caching system rebuild system for autowiring [DI] Only rebuild autowiring cache when actually needed Mar 27, 2016
@weaverryan
Copy link
Member Author

This is idea is now working, and it's quite simple and self-contained :). /cc @dunglas

Status: Needs Review

8000
$constructorParams = $constructor ? $constructor->getParameters() : array();
$constructorArgumentsForResource = array();
foreach ($constructorParams as $parameter) {
$constructorArgumentsForResource[] = $parameter->getClass();
Copy link
Member

Choose a reason for hiding this comment

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

you should store class names here rather than ReflectionClass instance.

Copy link
Member

Choose a reason for hiding this comment

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

and this misses several cases which impact the autowiring:

  • default options for args
  • classes which don't exist (but autowiring working because the typehint allows injecting null). This would trigger a ReflectionException in your code here, thus breaking autowiring
  • setters (as autowiring supports them now IIRC)

@stof
Copy link
Member
stof commented Mar 27, 2016

status: needs work

@weaverryan weaverryan force-pushed the autowiring_smart_cache branch from e8598ee to d0b600a Compare March 29, 2016 01:49
@weaverryan
Copy link
Member Author

@stof yes, thank you so much! Those were really great cases I hadn't thought of before! I refactored to store a string representation of the arguments in the resource, which pretty much catches all the cases in a very simple way. It may over-match on some things, like changing an argument's name, but not its type-hint - but I think that's a micro-optimization (for the dev env) that would be much more complex to implement.

The one case that's still not covered - and never was with the old method - is a non-existent class type hint suddenly becoming existent (i.e. a new lib was installed). But, in practice, this is quite rare and installing new packages cause a cache refresh. Also, that is the current behavior anyways.

Status: Needs Review

// of determining valid "setter" methods
foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
$name = $reflectionMethod->getName();
if (isset($methodsCalled[$name]) || $reflectionMethod->isStatic() || 1 !== $reflectionMethod->getNumberOfParameters() || 0 !== strpos($name, 'set')) {
Copy link
Member

Choose a reason for hiding this comment

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

isset($methodsCalled[$name]) will never be set, as $methodsCalled is undefined


public function testIsFreshSameConstructorArgs()
{
$oldResource = AutowirePass::createResourceForClass(

Choose a reason for hiding this comment

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

@weaverryan
Copy link
Member Author

Comments handled!

In the last commit, I tried to get more fine-grained on the argument info we need. I had this at one point earlier, but decided to use the string-casting method because it makes the code simpler and potentially less buggy (i.e. is there some edge-case that this is missing?). The string casting is overly-eager, but that means it errs on the side of clearing the cache too often, which is not a big deal. If you guys do like the simple method better, we can revert my most recent commit and go back. That would still be way better than the current situation :).

Thanks!

@fabpot
Copy link
Member
fabpot commented Apr 3, 2016

Thank you @weaverryan.

@fabpot fabpot closed this in c130bd6 Apr 3, 2016
@@ -278,4 +310,25 @@ private function addServiceToAmbiguousType($id, $type)
}
$this->ambiguousServiceTypes[$type][] = $id;
}

static private function getResourceMetadataForMethod(\ReflectionMethod $method)
Copy link
Member

Choose a reason for hiding this comment

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

private static

Copy link
Member

Choose a reason for hiding this comment

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

Good catch, see 804b924

Copy link
Member

Choose a reason for hiding this comment

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

👍

@nicolas-grekas
Copy link
Member

@weaverryan or anyone else, could you please have a look at the current test failures? They are related to this PR.

{
$this->assertTrue($this->resource->isFresh($this->time), '->isFresh() returns true if the resource has not changed in same second');
$this->assertTrue($this->resource->isFresh($this->time + 10), '->isFresh() returns true if the resource has not changed');
$this->assertFalse($this->resource->isFresh($this->time - 86400), '->isFresh() returns false if the resource has been updated');
Copy link
Contributor

Choose a reason for hiding this comment

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

Ok it this line, the object is returned instead of false.

HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 3, 2016
HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 3, 2016
HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 3, 2016
HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 3, 2016
HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 3, 2016
HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 3, 2016
nicolas-grekas pushed a commit that referenced this pull request Apr 4, 2016
nicolas-grekas added a commit that referenced this pull request Apr 4, 2016
This PR was squashed before being merged into the 3.1-dev branch (closes #18422).

Discussion
----------

[DependencyInjection] Fix tests of #18144

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | ~
| License       | MIT
| Doc PR        | ~

Commits
-------

5e7dbae [DependencyInjection] Fix tests of #18144
@weaverryan weaverryan deleted the autowiring_smart_cache branch April 4, 2016 11:25
@weaverryan
Copy link
Member Author

Ah, sorry about that @nicolas-grekas! I made a mistake on my final commits! The linked PR did not fix the issue - but I added a comment here: https://github.com/symfony/symfony/pull/18422/files#r58362092. I'll make sure that either @HeahDude will fix it (if he's nice enough and has time), otherwise I'll add a PR to fix it :)

HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 4, 2016
HeahDude added a commit to HeahDude/symfony that referenced this pull request Apr 13, 2016
fabpot added a commit that referenced this pull request Apr 14, 2016
This PR was merged into the 3.1-dev branch.

Discussion
----------

fix Autowiring tests of #18144

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| Tests pass?   | yes
| Fixed issue | #18422 (comment)
| License       | MIT

Commits
-------

0cbf04a [DI] fix Autowiring tests of #18144
tgalopin pushed a commit to tgalopin/symfony that referenced this pull request Apr 14, 2016
@fabpot fabpot mentioned this pull request May 13, 2016
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.

10 participants
0