What happens from a performance perspective, if you create the BeanCacheKey directly from the parameters of implResolveByType(Type injectionPointType, Class<?> injectinPointClass, Annotation... Qualifiers)? We can't be faster than that (and of course remove the array copy and sort operations from the BeanCacheKey implementation). If that is not fast enough, I would go with the caching of the result of InstanceImpl#resolveBeans The cache should be a transient, not synchronized or volatile class attribute, since the result will never change and computing it twice is not slower than the current solutionÅ
Cheers, Arne Am 21.01.13 11:21 schrieb "Romain Manni-Bucau" unter <[email protected]>: >i tried several enhancements in BeancacheKey but none was enough (maybe i >didnt cut the right part) > >*Romain Manni-Bucau* >*Twitter: @rmannibucau <https://twitter.com/rmannibucau>* >*Blog: >**http://rmannibucau.wordpress.com/*<http://rmannibucau.wordpress.com/> >*LinkedIn: **http://fr.linkedin.com/in/rmannibucau* >*Github: https://github.com/rmannibucau* > > > >2013/1/21 Arne Limburg <[email protected]> > >> Both solutions seem not to be perfect. >> >> >> What about improving the BeanCacheKey performance? >> >> The creation of the bean cache key uses many computations, what about >> simply removing them, i.e. if we remove the sorting of the qualifiers, >>it >> would potentially end up in more cache entries for the same set of >> annotations, but how often does this occur in practice, event the >>copying >> of the array could be removed. >> Maybe also the path to the bda should be replaced by the injection point >> class. This would blow up the cache, but maybe the performance >>improvement >> is it worth? >> >> Cheers, >> Arne >> >> Am 21.01.13 10:51 schrieb "Romain Manni-Bucau" unter >> <[email protected]>: >> >> >well didn't manage to find a lot of optim. The only relevant one i >>found >> >consists in 2 steps: >> > >> >1) cache the BeanCacheKey used for the instance >> >2) cache results of select >> > >> >here a proto (patch for trunk): https://gist.github.com/4584921 >> > >> >it solves pretty well the isAmbiguous() get() pattern >> > >> >here the perf: >> > >> >direct: 21ms >> >instance: 3257ms >> >direct: 0ms >> >instance: 2670ms >> >direct: 0ms >> >instance: 2790ms >> >direct: 0ms >> >instance: 2540ms >> >direct: 0ms >> >instance: 2717ms >> >direct: 0ms >> >instance: 2790ms >> > >> >do you think it's worth to use it or sthg close? >> > >> >*Romain Manni-Bucau* >> >*Twitter: @rmannibucau <https://twitter.com/rmannibucau>* >> >*Blog: >> >**http://rmannibucau.wordpress.com/*<http://rmannibucau.wordpress.com/> >> >*LinkedIn: **http://fr.linkedin.com/in/rmannibucau* >> >*Github: https://github.com/rmannibucau* >> > >> > >> > >> >2013/1/21 Romain Manni-Bucau <[email protected]> >> > >> >> you are right the cache is well done...but we use it. >> >> >> >> let me explain: if i use a direct injection i have the instance >>itself >> >>and >> >> all is fine. If not we go through the resolution and as you said we >>use >> >>the >> >> cache. >> >> >> >> To use the cache we use a key (since that's a map) and the key is a >> >> BeanCacheKey: that's what takes time: mainly its construction >> >> >> >> I'll have a look if it can be enhanced a bit >> >> >> >> FYI here is my test: >> >> >> >> public class TmpInstanceImpl extends AbstractUnitTest { >> >> @Test >> >> public void perf() >> >> { >> >> >> >> final Collection<Class<?>> classes = new >>ArrayList<Class<?>>(); >> >> classes.add(Foo.class); >> >> classes.add(DirectInjection.class); >> >> classes.add(InstanceInjection.class); >> >> >> >> startContainer(classes); >> >> >> >> final Bean<?> dir = >> >> >> >>>>getBeanManager().resolve(getBeanManager().getBeans(DirectInjection.clas >>>>s) >> >>); >> >> final DirectInjection di = (DirectInjection) >> >> getBeanManager().getReference(dir, DirectInjection.class, >> >> getBeanManager().createCreationalContext(dir)); >> >> Assert.assertNotNull(di); >> >> >> >> final Bean<?> inst = >> >> >> >>>>getBeanManager().resolve(getBeanManager().getBeans(InstanceInjection.cl >>>>as >> >>s)); >> >> final InstanceInjection ii = (InstanceInjection) >> >> getBeanManager().getReference(inst, InstanceInjection.class, >> >> getBeanManager().createCreationalContext(inst)); >> >> Assert.assertNotNull(ii); >> >> >> >> long start, end; >> >> >> >> for (int i = 0; i < 10; i++) { >> >> start = System.nanoTime(); >> >> for (int k = 0; k < 1000000; k++) { >> >> di.resolve(); >> >> } >> >> end = System.nanoTime(); >> >> System.out.println("direct: " + >> >> TimeUnit.NANOSECONDS.toMillis(end - start) + "ms"); >> >> >> >> start = System.nanoTime(); >> >> for (int k = 0; k < 1000000; k++) { >> >> ii.resolve(); >> >> } >> >> end = System.nanoTime(); >> >> System.out.println("instance: " + >> >> TimeUnit.NANOSECONDS.toMillis(end - start) + "ms"); >> >> } >> >> >> >> shutDownContainer(); >> >> } >> >> >> >> public static class Foo { >> >> public void touch() { >> >> // no-op >> >> } >> >> } >> >> >> >> public static class DirectInjection { >> >> @Inject >> >> private Foo foo; >> >> >> >> public void resolve() { >> >> foo.touch(); >> >> } >> >> } >> >> >> >> public static class InstanceInjection { >> >> private static final AnnotationLiteral<Default> AL = new >> >> DefaultLiteral(); >> >> >> >> @Inject @Any >> >> private Instance<Foo> foo; >> >> >> >> public void resolve() { >> >> foo.select(AL).get().touch(); >> >> } >> >> } >> >> } >> >> >> >> and here what looks like the result: >> >> >> >> direct: 5ms >> >> instance: 10191ms >> >> direct: 0ms >> >> instance: 10487ms >> >> direct: 0ms >> >> instance: 9722ms >> >> direct: 0ms >> >> instance: 9171ms >> >> direct: 0ms >> >> >> >> *Romain Manni-Bucau* >> >> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>* >> >> *Blog: >> >>>>**http://rmannibucau.wordpress.com/*<http://rmannibucau.wordpress.com/> >> >> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau* >> >> *Github: https://github.com/rmannibucau* >> >> >> >> >> >> >> >> 2013/1/20 Arne Limburg <[email protected]> >> >> >> >>> Yes, that's interesting and unexpected. >> >>> >> >>> Can you please profile, where the time is lost? >> >>> In theory, we even could cache the instance when it is a normal >>scoped >> >>> proxy. >> >>> >> >>> But it is interesting for the overall performance, where the time is >> >>> lost... >> >>> >> >>> Cheers, >> >>> Arne >> >>> >> >>> >> >>> Am 20.01.13 19:43 schrieb "Romain Manni-Bucau" unter >> >>> <[email protected]>: >> >>> >> >>> >Well it doesnt seem to be as efficient as expected. Replacing a >>plain >> >>>old >> >>> >injection by an instance i expected no more than x3 in execution >>time >> >>>but >> >>> >was easily x10...and i had less than 5 beans. >> >>> > >> >>> >Not sure what takes time...thought to cache the whole result in the >> >>> >instance but if you have better ideas it is still open for 1.1.8 >>and >> >>> 1.2.0 >> >>> >:) >> >>> >Le 20 janv. 2013 19:24, "Arne Limburg" >> >>><[email protected]> a >> >>> >écrit : >> >>> > >> >>> >> Hi Romain, >> >>> >> >> >>> >> It is cached in the InjectionResolver, that should suffice. >> >>> >> >> >>> >> >> >>> >> Cheers, >> >>> >> Arne >> >>> >> >> >>> >> Am 19.01.13 17:44 schrieb "Romain Manni-Bucau" unter >> >>> >> <[email protected]>: >> >>> >> >> >>> >> >Hi guys, >> >>> >> > >> >>> >> >is there any reason >> >>> >> >why >> >>>org.apache.webbeans.inject.instance.InstanceImpl#resolveBeans() is >> >>> >>not >> >>> >> >cached in the instance of InstanceImpl (whatever the cache is - >>a >> >>> >>volatile >> >>> >> >var, an atomicref or even a synchronized block)? >> >>> >> > >> >>> >> >typically doing this pattern: if (!instance.isAmbiguous()) { >>return >> >>> >> >instance.get(); } you'll call it twice for nothing (and it can >>be >> >>>O(n) >> >>> >> >with >> >>> >> >n the numbe rof beans)...or just regarding runtime it seems >>weird >> >>>no? >> >>> >> > >> >>> >> >wdyt? >> >>> >> > >> >>> >> >*Romain Manni-Bucau* >> >>> >> >*Twitter: @rmannibucau <https://twitter.com/rmannibucau>* >> >>> >> >*Blog: >> >>> >> >**http://rmannibucau.wordpress.com/*< >> >>> http://rmannibucau.wordpress.com/> >> >>> >> >*LinkedIn: **http://fr.linkedin.com/in/rmannibucau* >> >>> >> >*Github: https://github.com/rmannibucau* >> >>> >> >> >>> >> >> >>> >> >>> >> >> >> >>
