Compile- vs load-time weaving performance in Spring

  • Yesterday I had pleasure to participate in Java Developers’ Day in Kraków, Poland. It was a great experience to seeMark Richards (author of Java Message Service) and Scott Davis (Groovy Recipes) giving a talk. Also I really enjoyedWojciech Seliga speak about code review. He works for Atlassian and shown a bit of Crucible, but his main point was that code review is not about looking for bugs made by other developers. It is rather an agile process of getting to know the code.

     

    I could write much more about JDD, of course starting from "you should regret if you haven’t been there", but I am quite sure that you are already waiting for the main topic. Let’s just say, that there is a chance that JDD will take 2 days in the next year and I will do my best to be there.

     

     

    After reading my previous post one of my friends asked about performance of creating objects marked as@Configurable. He wants to inject EntityManager or other custom dependencies to his JPA POJOs but is concerned about performance. Because many thousands of objects are created manually or by Hibernate during the application life, overhead introduced by Spring aspect injecting dependencies each time new operator is called may be significant. There is no sense in talking about performance, I will simply measure everything!

     

    But before we start our performance comparison test: I haven’t yet explained how to enable compile-time weaving instead of load-time. First a word of explanation: CTW weaves aspect during compilation phase when building your application using Maven. LTW does that when the class is loaded within the JVM. Because both approaches should weave the same aspect and produce the same code, true performance of object creation should be the same despite the weaving method. But we will check that out too.

     

    As you probably expect, switching from LTW to CTW is only a matter of configuration, no code must be changed. All you need to do is remove LTW Spring agent from pom.xml (surefire plugin configuration) and references to the agent when running JVM (on server and unit tests from your IDE). When you got rid of LTW, enable CTW in no time (pom.xml):

     

     

    <plugin>

    <groupId>org.codehaus.mojo</groupId>

    <artifactId>aspectj-maven-plugin</artifactId>

    <configuration>

    <complianceLevel>1.6</complianceLevel>

    <aspectLibraries>

    <aspectLibrary>

    <groupId>org.springframework</groupId>

    <artifactId>spring-aspects</artifactId>

    </aspectLibrary>

    </aspectLibraries>

    </configuration>

    <executions>

    <execution>

    <goals>

    <goal>compile</goal>

    <goal>test-compile</goal>

    </goals>

    </execution>

    </executions>

    </plugin>

     

     

     

    Nothing to be explained, maybe except the complianceLevel, which corresponds to your JDK version. You must also replace:

     

     

    <context:load-time-weaver/>

     

     

    with:

     

     

    <context:spring-configured/>

     

     

    In your Spring context configuration file.

     

    Now, when we know how to switch back and forth from LTW to CTW, let’s run some performance tests. I used Reservation class introduced in previous posts for testing creation performance, but I added three dependencies via transient fields in this POJO:

     

     

     

    @PersistenceContext

    private transient EntityManager em;

     

    private transient TicketService ticketService;

     

    @Resource

    private transient JavaMailSender javaMailSender;

     

     

    The TicketService is being injected using the configuration below:

     

     

    <bean class="com.blogspot.nurkiewicz.reservations.Reservation" scope="prototype" lazy-init="true">

    <property name="ticketService" ref="ticketService"/>

    </bean>

     

     

    By testing three beans with different injection techniques I wanted to find out, whether the type of injection has different performance impact.

     

    The test scenario was to first create 1000 instances of Reservation class to warm up JVM and then measure the time of creating 50 thousand instances and putting them in previously created array to partially prevent GC. Objects were created in the following weaving environment:

    • none – no weaving has been applied
    • CTW (no dependencies) – CTW enabled and @Configurable annotation added to Reservation class, but no dependencies injected (@PersistenceContext@Resource and XML configuration removed)
    • CTW (EM) – CTW with EntityManager injected
    • CTW (<property>) – CTW with dependency configured in Spring XML context file being injected
    • CTW (@Resource) – CTW with dependency autowired using standard @Resource annotation
    • CTW (all) – CTW with all three dependencies listed above injected
    • LTW (no dependencies) – like above but using LTW
    • LTW (EM) – like above but using LTW
    • LTW (<property>) – like above but using LTW
    • LTW (@Resource) – like above but using LTW
    • LTW (all) – like above but using LTW

     

    Each test creating 50K instances has been repeated 8 times with very low standard deviation. I measured the time it took JVM to create all the instances and scaled it to the number of instances being created per second. Bigger value is better.

     

    Probably you start to feel bored so I skip detailed results and give you this nice chart:

     

     


    The results are a bit surprising for me for two reasons. First, creating objects marked as @Configurable is less than 4 times slower than creating ordinary objects using new operator. I assumed that creating new objects on heap is so greatly optimized that adding the overhead of Spring aspect scanning the class and trying to inject dependencies to completely unknown class would be tremendous. But even if single dependency is being injected using @Resource or XML configuration, creation time is reasonable. In fact, 4-5 times slower when the object is created by Hibernate is something that is almost impossible to measure and see in real environment – simply database and network connectivity brings much bigger overheads, making injection time insignificant. Also, just as I thought, there is no big difference between LTW and CTW when there comes to performance, so use whichever you like. Or at least do not take performance into account when deciding.

     

    The second surprise, negative this time, was the time of creating objects with injected EntityManager. Somehow it is almost 30 times slower than normal object creation and 6 times slower than injecting other custom Spring beans. It is not the subject of this post to find out what happens behind the scenes with EntityManager (probably Spring does some additional magic with EntityManager proxy, maybe I will investigate this in the future), but the results are disturbing.

     

    To summarize: using @Configurable annotation and injecting your Spring beans probably won’t be performance issue in your project. Of course my test isn’t definite and you should check this in your particular case, but the benefits of Spring injection into domain objects can’t be overestimated. But be careful when injecting EntityManager directly to your domain objects – the performance impact is somewhat significant and when creating thousands of objects your application might slow a little bit.

     

     


    Test environment: Intel Core Duo T2050 1.6 GHz, 1 GiB RAM, Windows XP SP2, JDK 1.6.0_14

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值