-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DI] Review the performance of the service container #25159
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
Comments
I would rename the issue as: create a more realistic benchmark for containers. |
Thanks for the insights. This benchmark literally starts saying "we're making this benchmark because a while ago someone published a benchmark which was wrong". So maybe this benchmark is wrong too to measure real-life container performance. |
One case that is not handled well by the current benchmark is the "unused services" one: because we're in PHP, running in short lived cycles, we don't need all services all the time. That's a significant aspect of the performance of a PHP container: will it be fast also when a serious number of services is defined, but only a few of them are actually used per request? |
Regarding the tests themselves:
Without those, this benchmark is a bit like the JIT tests done in PHP: awesome results for the tests and then realising it doesn't change anything in real-life applications, because that's not how things are used. On Symfony side, from what I understood the slowness comes from the aliases which we are keeping, so we have an additional check to see if the service is an alias or not. Apparently this is not trivial to remove in the compiled container, but that would bring better performances for sure. |
Closing because now it's clear that this benchmark is too synthetic and it won't help us improving the performance of real apps. Thanks! |
@javiereguiluz Let's please reopen this. I believe assumptions of two previous posters are incorrect. This needs more investigation at least.
I modified the benchmark to call
No it isn't. You assume cold test of this benchmark compiles the container. It doesn't. It only creates new instance of already compiled container,
That's assumption which isn't based on facts. What makes you think results would be different when hierarchy of services is distributed more randomly?
It's me who concluded this (and also @nicolas-grekas later), but after further investigation I found we were wrong. Commenting out this section in Container.php had no significant impact. There is unknown reason why is Symfony slower and I would like you guys to help find it. Now, I've forked the benchmark and upgraded it to use Symfony 4.0 DI component. And I reduced the impact zone by reducing benchmark to this small simple script. When lines in Container.php linked above get commented, logical assumption (and debugger confirms) that both Containers execute same things. Despite that, Symfony DI takes 3x as much time as Yaco container. It's especially obvious when xdebug is disabled. So let's find out why. |
Can you try swapping the tested containers, are the results similar? I noticed that the order of such microbench can have a significant effect sometimes. |
Ok I swapped them, results still seem similar :/ |
I think you can reclaim performance by removing most of the inheritance tree, like the interfaces. They're not needed for the bench. You can also remove the "invalid behavior" argument. |
@nicolas-grekas About which instance of "invalid behavior" are you talking about? I see that gets aren't using it and even if this shouldn't affect the performance. |
I would also like to know. I think you didn't look at my minimalistic benchmark script? Please clone and take a look. There is nothing more there to remove. |
I talking about the second argument of |
@nicolas-grekas I'm looking at the code of tests and I see second parameter is not used: https://github.com/kocsismate/php-di-container-benchmarks/blob/master/src/Container/Symfony/Test1.php Throwing surely takes time and using |
I can confirm removing second argument in
Now we can close this. |
This PR was merged into the 3.4 branch. Discussion ---------- [DI] Optimize Container::get() for perf | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #25159 | License | MIT | Doc PR | - As outlined in #25159, our beloved container suffers from a perf hit just because it has a second argument, and this second argument's default value makes it slower. Let's fix this by inlining the value. This will put Symfony at a better rank on eg: https://github.com/kocsismate/php-di-container-benchmarks I benched also with the following script. The result is surprising (but matches the finding in #25159): without the patch, it takes 2s, and with the patch, it's down to 1s (opcache enabled). ```php require './vendor/autoload.php'; use Symfony\Component\DependencyInjection\Container; $c = new Container(); $c->set('foo', new \stdClass()); $i = 10000000; $s = microtime(1); while (--$i) { $c->get('foo'); } echo microtime(true) - $s, "\n"; ``` Commits ------- 4fe2551 [DI] Optimize Container::get() for perf
Thank you @ostrolucky for the thorough investigation! I am open to suggestions in order to improve my benchmark. :) And @javiereguiluz I'll change the line saying "my test is better than the last one was" because it sounds a bit arrogant. :S My idea to measure "cold", "semi-warm" and "warm" performance came after Ocramius' suggestion (kocsismate/php-di-container-benchmarks#4 (comment)). Basically, these test suites do the following:
Of course it's useful to improve "warm" performance, but I think bootstrap and autoloading time of the container can also be very important, especially when the retrieved object graph is not big or when you don't call the All in all, I believe "cold" test suites are the most informative ones because they simulate a complete request with workloads which are similar to what "real life" apps might have. But I am honestly curious about your opinion, as you probably know more about the topic. |
@kocsismate I just copied your literal words from your benchmark page, where you say that the previous benchmark was bad and yours is better. I don't think that's arrogant: some things are better than others. You are not insulting the other one: |
Yeah, I know they are mine :) But I didn't like them at all when I saw them again. Maybe the sentence is not arrogant, but inelegant, so thanks for bringing it up! |
On the Symfony Slack, @theofidry shared the following benchmark about service containers: https://rawgit.com/kocsismate/php-di-container-benchmarks/master/var/benchmark.html
Given that Symfony's container is compiled, the results should be much better. We could review that benchmark and if we can verify the results, try to improve things. Thanks.
The text was updated successfully, but these errors were encountered: