-
Notifications
You must be signed in to change notification settings - Fork 11.2k
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
[5.8] Track abstracts being resolved, fire resolving events once #26112
Conversation
…lready on this stack
*/ | ||
protected function pendingInResolveStack($object) | ||
{ | ||
foreach ($this->resolveStack as $resolving) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure we have to resolve the last element on each loop. I would make sense to extract it to a variable before.
Or even slicing the resolveStack.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also work:
return collect($this->resolveStack)->slice(0, -1)->contains(function ($resolving) {
$object instanceof $resolving;
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does, but it's a big performance hit.
phpbench run tests/Container/ContainerTest.php --revs=100
+-------------------------------------------------------+------------------+-------------------+
| subject | tag:collect:mean | tag:original:mean |
+-------------------------------------------------------+------------------+-------------------+
| testResolvingCallbacksAreCalledForSpecificAbstracts | 5,917.960μs | 4,046.610μs |
| testResolvingCallbacksAreCalledOnceForImplementations | 23,971.640μs | 9,072.640μs |
| testResolvingCallbacksAreCalledForNestedDependencies | 99,831.230μs | 61,386.800μs |
+-------------------------------------------------------+------------------+-------------------+
original
is this PR, collect
is your alternative.
Note that the loop breaks through return as soon as a match is found.
Does your solution even make sense though? What if you have a resolving stack with two objects of the same type but that are totally different, unrelated instances? You need to call the resolving callback for each instance in that case but you're checking for instanceof and will exclude one of them? |
Two independent instances of a certain type will not end up in the same stack except when there is a cyclic dependency anyway. The stack will contain a trace of classes that are being resolved. Test
The test asserts that resolving
|
What is the performance impact of this on the typical Laravel web request? |
Closing pending inactivity. |
Fixes #23699 by tracking abstracts that are currently being resolved.
If an object is built that is an
instanceof
of an object that is already on the stack, firing the resolving() callbacks is inhibited.These callbacks are fired eventually when the
instanceof
object is resolved.This is a continuation of #23701.
I've ran some benchmarks on the adaptions of the
ContainerTest
s that interacts a lot with the$resolveStack
because of the nested interfaces.E.g., for
testResolvingCallbacksAreCalledForNestedDependencies
an adaption that resolves many times:I've also adapted and benched:
testResolvingCallbacksAreCalledOnceForImplementations
testResolvingCallbacksAreCalledForSpecificAbstracts
https://github.com/tomlankhorst/framework/tree/resolve-stack-bench
https://github.com/tomlankhorst/framework/pull/1/files
Using PHPBench, 10 revs, 10 its (for a total of 10.000 calls per resolve).
phpbench run tests/Container/ContainerTest.php --tag=no_resolve_stack --store --retry-threshold=4 --revs=10 --iterations=10
Comparing this to the current master without the resolve stack (that shows the erroneous behaviour of #23699):
So, there's an average performance impact of 10% on resolving. I realize this impact is significant but I also realize that the current behaviour is not acceptable.