7

We're using Spring (3.0.5) AOP with @AspectJ style annotations and <aop:aspectj-autoproxy/> . We use it for transactions, auditing, profiling etc. It works fine except that the startup time of the application is continuously growing as more code is being added.

I have done some profiling and found that most of the time is spent during Spring container initialization, more specifically org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory) - takes about 35 sec. org.springframework.aop.support.AopUtils.canApply(Pointcut, Class, boolean) - takes about 15 sec.

My goal is for the application to start in 5-10 seconds and not ~45 sec as it does now, so any tips would be much appreciated.

Yuval Rimar
  • 1,055
  • 12
  • 22
  • Jumping to conclusion that Spring AOP causes startup performance is hurried conclusion.( considering the weaving happens at runtime). Did you check stats of JVM using Jconsole or visualVm. Do you have a custom init method for some of your beans. Did you try using lazy-initialization. (by lazy-init property in bean)? – uncaught_exceptions Jan 21 '11 at 05:46
  • These are the steps I will follow. 1- Check JVM stats while loading normally. 2. Make beans lazy-init property to be default and then again check the jvm stat (memory usage et al). 3- If still there is no notable improvement, I will then shutdown aspect autoproxying. Like I mentioned, If I had to place a bet, I will be ready to bet that its not AOP weaving affecting load time. – uncaught_exceptions Jan 21 '11 at 05:46
  • I am pretty sure it is the weaving since i spent lots of time profiling with Yourkit, taking just thread dumps during startup and placing some breakpoints and all points to the AOP weaving. But I am curious when you say shutdown aspect autoproxying what's the alternative that you suggest? Thanks, Yuval – Yuval Rimar Jan 22 '11 at 22:10
  • Did you get any solution to this problem ? I am facing the same problem. –  Sep 02 '11 at 11:43
  • No, no solution, we just live with it... – Yuval Rimar Sep 07 '11 at 20:28
  • Adding 2 little aspects with 4 pointcuts doubled my startup time from 11 seconds to 22 seconds and tripled devtool restart time from to 2 to 6 seconds. Now I understand why the huge application at my workplace takes 150 seconds to startup... Oh, the beauty of overengineered frameworks! Time to buy JRebel I guess. – ASA May 06 '16 at 21:04

6 Answers6

6

I had the same issue, it turns out Spring AOP auto-proxying spends a LOT of time at startup loading classes with bcel (without caching, so loading again and again same classes like java.lang.Object...) when trying to figure out which advices apply. It can be somewhat improved by writing more fine-grained Point cuts (use within, @within for example) but I've found a solution that worked better if all your pointcuts are written with @annotation.

1) Desactivate auto-proxy with: spring.aop.auto=false

2) Write a custom subclass of AnnotationAwareAspectJAutoProxyCreator to filter beans to be decorated according to your own criteria, for example this one is based on package and annotations :

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,   TargetSource targetSource) {
  if (beanClass != null && isInPackages(beansPackages, beanClass.getName()) &&   hasAspectAnnotation(beanClass)) {
    return super.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  } else {
    return DO_NOT_PROXY;
  }
}

In my case startup time down from 60s to 15s.

I hope it will help someone and polar bears

alext
  • 186
  • 1
  • 3
5

From what you've posted it looks like your using Load Time Weaving which incurs a startup penalty because the system has to weave all the classes as they are being loaded. If your primary concern is startup time, then I would suggest you switch to Compile Time Weaving. You can find instructions on how to do this in the spring documentation (Chapter 6, Section 8) or in at the AspectJ site (http://www.eclipse.org/aspectj/docs.php)

Switching to Compile time weaving with the AspectJ compiler is relatively stragiht forward:

  1. Remove the <aop:aspectj-autoproxy/> notation from your context file.
  2. Add a aspectJ compile step to your build file. On the AspectJ site you should be able to find an ant plugin, codehaus has a maven plugin. Here are examples of how to us both.

For Maven:

<plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>aspectj-maven-plugin</artifactId>
     <version>1.3</version>
     <configuration>
     <verbose>true</verbose>
      <source>1.6</source>
      <target>1.6</target>
      <complianceLevel>1.6</complianceLevel>
      <showWeaveInfo>true</showWeaveInfo>
      <aspectLibraries>
        <aspectLibrary>
                                <groupId>org.springframework</groupId>
                                <artifactId>spring-aspects</artifactId>
                            </aspectLibrary>
                        </aspectLibraries>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>   
                            </goals>
                        </execution>
                    </executions>
                </plugin>

For Ant

 <taskdef
            resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
            <classpath>
                <pathelement location="${lib.dir}/AspectJ_1.6.8/aspectjtools.jar"/>
            </classpath>
        </taskdef>

  <iajc aspectPath="${file.reference.spring-aspects.jar}; ${build.classes.dir}/path/to/custom/aspects"
              classpath="${lib.dir}/AspectJ_1.6.8/aspectjrt.jar; ${javac.classpath}"
              inpath="${build.classes.dir}"
              destDir="${build.classes.dir}"
              showWeaveInfo="true" />
Karthik Ramachandran
  • 11,925
  • 10
  • 45
  • 53
3

Apparently this is a known issue if you have a lot of non-singleton beans. There seems to be a fix for Spring 3.1: https://jira.springsource.org/browse/SPR-7328

yorah
  • 2,653
  • 14
  • 24
1

I am not sure that it applies to your situtation, but Spring performance can be improved by empolying a CachingBeanFactory.

This usually applies when wiring beans, but depending on how your aspects are applied and wired, it might bring improvements.

Robert Munteanu
  • 67,031
  • 36
  • 206
  • 278
1

Do you have any circular dependency? That's what's killing my current app.

I know that's not really a solution but I would break up the context to run different services in different vms, SOA-style. That should allow all your apps to have a small startup time and that should also give you some flexibility to change the implementation of these services more easily, small amount of code to test, etc.

I didn't do that in one of my apps and now startup time is at about 3/4 mins which is crazy (we have a couple of thousand beans). That problem doesn't go away, it will only get worse, but if you try to do something about it too late, the app will be too big and too difficult to break up.

Another thing I would look into is hibernate, creating the session factory can be pretty slow.

Felipe Oliveira
  • 1,041
  • 9
  • 9
0

I had the same problem, before I change jdk1.7 back to jdk1.6. By jdk1.7, my app hang on “Initializing Spring root WebApplicationContext” for more tha 30 seconds. After I change back, it startup in 10sec.