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
Poor Performance with lots of Prototype Scoped Beans [SPR-9670] #14304
Comments
Kevin Mudrick commented Added test case which illustrates the performance difference (if you update the pom & re-run to switch between 3.0.7 and 3.1.2). Pull request: spring-attic/spring-framework-issues#33 Here are the results I get running locally: 3.0.7 Running org.springframework.issues.ReproTests ms % Task name 00906 014% Initializing 3.1.2 Running org.springframework.issues.ReproTests ms % Task name 00872 001% Initializing As you can see, creating lots of prototype-scoped beans is over 10x slower, while initialization is roughly the same. |
Chris Beams commented Thanks, Kevin. |
Chris Beams commented Just confirmed these results on my machine as well: 3.0.7
3.1.2
3.2.0.BUILD-SNAPSHOT (20120805.180303)
|
Phil Webb commented 3.0.7
3.2.0.BUILD-SNAPSHOT (before)
3.2.0.BUILD-SNAPSHOT (after)
|
Juergen Hoeller commented A quick update since this is still in progress: I've gone into three different areas where optimization is due, two of which are related to argument caching not properly working - in particular, with String literal arguments of which there are quite a few in this repro test. A bad != check where we should check !equals breaks static String detection... The good news: A !equals fix for String argument caching brings a radical improvement here, passing the test on 3.1.3 significantly faster than on 3.0.7. Of course, there is still room for improvement in 3.1's extensive argument conversion algorithm as suggested by Kevin and Phil; it just turns out to be less relevant once argument caching is fixed. Juergen |
Juergen Hoeller commented This generally relates to #12081 where we deactivated the caching of converted constructor argument values in order to avoid a race condition. It looks like worth reactivating with the slightly reordered algorithm there in the meantime. However, that code for #12081 does not actually make a big difference in the present test scenario since our broken String literal caching (as outlined above) is overwhelmingly the dominant factor here. |
Juergen Hoeller commented Marking this as resolved for the time being, with our expression detection properly handling cached String literals. While there is still room for improvement, the regression can be considered as fixed since we even beat 3.0.7 on performance in such a scenario now. Juergen |
Jonatan Jönsson commented Related to ReflectionUtils:
In my experiments the old uncached version: Whereas my modified version: This means that with a code base with an average of 6 (non-object) methods per class you save 9 tenths time. My reasoning is that when 2/3 of the calls can use the cache, it should cache. Especially when reflection is concerned. If yoy're worried about the cache growing a simple Set of strings, guarding the more expensive lookups, like this:
Gives 1/3 better performance. |
Kevin Mudrick opened SPR-9670 and commented
We are seeing a pretty substantial performance hit with the creation of large quantities of prototype-scoped beans in the 3.1.x branch versus 3.0.x (and 2.5.6)
In our example, we have call context.getBean() with a bean consisting of 2 levels of nested bean referenced, in a pretty large loop.
3.0.7: 40604ms
3.1.2: 685150ms
The only difference between these runs is the version of the spring dependencies.
After profiling using YourKit, I found the hotspots in 3.1.x to be in the following places:
org.springframework.beans.TypeConverterDelegate: This seems to be the bigger problem.
The changes introduced in 3.1 (specifically, in commit 6f14673) to findDefaultEditor() end up (expensively) initializing an editor registry every time this is called. Since we get here each time we apply a property on every bean creation, this really adds up. Previously, the commented-out code ended up shortcutting this. I found that replacing the commented out code (the part that relied on the now-removed PropertyTypeDescriptor/PropertyDescriptor with static use of PropertyEditorManager.findEditor(), cuts down on the slowness considerably, at the expense of relying on java.beans - which a few commit comments seem to indicate is something to be avoided for better platform compatibility.
org.springframework.core.convert.Property: This also seems to be a problem.
The overhead of the annotation parsing via reflection is already noted in #13981 - but that issue doesn't seem to mention this example. My profiling is showing that this is being constructed for every property found on every bean being created. With lots of prototype beans - this comes to light pretty quickly. Perhaps if ReflectionUtils used a similar caching strategy to apache commons-beanutils PropertyUtilsBean for annotations, this performance hit could be mitigated.
Affects: 3.1.2
Issue Links:
0 votes, 6 watchers
The text was updated successfully, but these errors were encountered: