[Crossposted to Spring AOP forum and AspectJ Users list]
We have a Tomcat 6 web application that uses Spring 3.0.3 and AspectJ
1.6.10. Depending upon the hardware, startup times range from 80 seconds on
our best build systems, to 2 minutes in production, to close to 4 minutes in
some situations on older build systems.
We have determined by disabling the wiring of aspects, i.e. removing
<aop:aspectj-autoproxy/>, that Spring AOP is responsible for approximately
60% of the startup cost.
Profiling with YourKit showed the vast majority of the time is beneath
org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository. The name of
the class makes me fear that we are loading and processing the same class
files over and over again. However, even if a caching Repository were used,
the use pattern of Repository in
org.aspectj.weaver.reflect.Java15AnnotationFinder indicates that such
caching would be wasted:
bcelRepository.loadClass()
bcelRepository.clear()
Putting aside the non-caching nature of the Repository, we had a thought
that our Pointcuts were not "good", according to Section 7.2.3.5 "Writing
Good Pointcuts" of the Spring documentation [1]. Many only had @within(<Java
1.5 Annotation>). So we added execution constraints to only look at our own
classes. But this did not significantly nor sufficiently help.
Before I ask a few questions about possible solutions, here are few more
details about our application:
- We are using Spring AOP with AspectJ annotations, i.e. @Aspect with
@Component
- We essentially have one big ApplicationContext that loads beans (450+) and
Aspects (25)
- Most beans are discovered through component-scan'ing the classpath
separately for a list of 35+ packages
Here are my questions:
- Does the Spring AOP processing analyze beans in the context, or classes on
the classpath? If it processes the beans in the context, does that include
beans in parent contexts?
- Are we simply analyzing too many beans against too many aspects? Would
creating separate contexts that contain the beans for that layer, and only
the aspects that apply to them improve performance sufficiently?
- Should we attempt to convert to compile time weaving? We currently make
use of Spring's @Order on several of our @Aspects, so this may not be easy,
or even possible. Would this just move the cost from runtime to compile, or
does it actually reduce the cost?
- Should we try to modify AspectJ itself to have a
CachingClassLoaderRepository, and fix the pattern to only clear the
Repository at the end of AOP processing? Although it appears to be getting
to the NonCachingClassLoaderRepository via
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreate.postProcessAfterInitialization
via org.springframework.beans.factory.support.AbstractBenFactory.getBean. So
it would appear to be going a bean at a time, and there might not be a good
place to clear the BCEL Repository.
Thanks in advance for reading this far, and any time you choose to spend
thinking about my problem!
-- Josh
[1]
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html
_______________________________________________
aspectj-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users