Spring Framework
  1. Spring Framework
  2. SPR-6252

Improve performance and memory usage when using @Configurable with a agent

    Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.5.6, 3.0 RC1
    • Fix Version/s: General Backlog
    • Component/s: Core
    • Labels:
    • Last commented by a User:
      true

      Description

      Hi,

      I will expose my problem.

      I'm writing Swing applications and I like using Spring in my client (not very common in a Swing application) because it is useful when you call some Remote Services (RMI, WS) by using the different Spring Proxy Clients or if you want to seperate your Business logic and GUI logic and so easy to test your gui.

      The problem using Spring in Swing application is when you're making a Swing application, you need to inject in your Controller/View (JPanel for instance) some beans Spring. But your JPanel is not instanciated by Spring (and you can't it).
      To resolve this problem, I found 2 solutions

      • create a kind of ServiceLocator (where the applicationContext is instanciated). When you want to inject a bean Spring, you must ServiceLocator.getInstance().getYourSpringBean(). It is very old-fashioned and has all problems related to static singleton (not easy too test, problem in Netbeans RCP like Tomcat for static stuffs ...).
      • use @Configurable on your panel (not instanciated by Spring) to inject with @Autowired in some spring bean. It very clean and elegant on my point of view.

      I made a small application with @Configurable and it works but it reveals some performance and memory usage problems.
      When you use a GUI with a ServiceLocator, the startup of this application is something like 2 s (1s for Swing and 2s for spring context in lazy mode) and the memory usage is 10 mo.
      When you use the same GUI with @Configurable (with the spring agent) the startup of the application is something like 10 s and the memory usage is 50-60 mo.

      I attached a very small application example to show the problem. With this sample,
      when you use a GUI with a ServiceLocator, the startup of this application is something like 900 ms (250 ms for Swing and 650 ms for spring context in lazy mode) and the memory usage is 1.2 mo.
      When you use the same GUI with @Configurable (with the spring agent) the startup of the application is something like 3.6 s (1350 ms for Swing and 2280 ms for spring context in lazy mode) and the memory usage is 8 mo.

      So the performance and memory usage is degraded by 5.

      I tested with Spring 2.5.6 and with 3.0RC1 and the behaviour is the same.

      Can you explain this behaviour? Is it normal? Maybe I have misconfigured my applicationContext. Can I specify the package where @Configurable classes are located to improve performance?

      Honnestly, with these problems, @Configurable is just unuseable for production GUI application but only for unit tests.

      Alexandre

        Activity

        Hide
        Alexandre Navarro added a comment -

        The sample.

        Show
        Alexandre Navarro added a comment - The sample.
        Hide
        Alexandre Navarro added a comment -

        I think it is possible to force with META-INF/aop.xml to load with the agent only some classes of a package (Adrian Coyler told me that last week during the "Rencontre Spring at Paris"), but I did not try it if it works better.

        Show
        Alexandre Navarro added a comment - I think it is possible to force with META-INF/aop.xml to load with the agent only some classes of a package (Adrian Coyler told me that last week during the "Rencontre Spring at Paris"), but I did not try it if it works better.
        Hide
        Ramnivas Laddad added a comment -

        This very much looks like a problem due to wide application of LTW. If you can add META-INF/aop.xml (anywhere in classpath) with content similar to the following, you should see substantial performance gains:

        <aspectj>
        <weaver>
        <exclude within="com.yourcompany.app.ui..*"/> <!-- make sure your @Configurable classes are selected by this, and if possible very little else -->
        </weaver>
        </aspectj

        Show
        Ramnivas Laddad added a comment - This very much looks like a problem due to wide application of LTW. If you can add META-INF/aop.xml (anywhere in classpath) with content similar to the following, you should see substantial performance gains: <aspectj> <weaver> <exclude within="com.yourcompany.app.ui..*"/> <!-- make sure your @Configurable classes are selected by this, and if possible very little else --> </weaver> </aspectj
        Hide
        Alexandre Navarro added a comment -

        I tried with

        <aspectj>
        <weaver>
        <include within="fr..*"/> <!-- make sure your @Configurable classes are selected by this, and if possible very little else -->
        </weaver>
        </aspectj

        The result on my PC is :

        When you use a GUI with a ServiceLocator, the startup of this application is something like 900 ms (250 ms for Swing and 650 ms for spring context in lazy mode) and the memory usage is 1.2 mo.

        When you use the same GUI with @Configurable (with the spring agent) the startup of the application is something like 3.6 s (1350 ms for Swing and 2280 ms for spring context in lazy mode) and the memory usage is 8 mo.

        When you use the same GUI with @Configurable (with the spring agent) with the aop.xml the startup of the application is something like 2.4 s (800 ms for Swing and 1500 ms for spring context in lazy mode) and the memory usage is 5.1 mo.

        To sum up,

        GUI with ServiceLocator GUI with agent GUI with agent and aop.xml
        Startup Time 900 ms 3600 ms 2400 ms
        Memory 1.2 mo 5.1 mo 8.3 mo

        The aop.xml improves the performance and memory usage but not a lot compared to the version without agent (notably the memory is very problematic)

        Show
        Alexandre Navarro added a comment - I tried with <aspectj> <weaver> <include within="fr..*"/> <!-- make sure your @Configurable classes are selected by this, and if possible very little else --> </weaver> </aspectj The result on my PC is : When you use a GUI with a ServiceLocator, the startup of this application is something like 900 ms (250 ms for Swing and 650 ms for spring context in lazy mode) and the memory usage is 1.2 mo. When you use the same GUI with @Configurable (with the spring agent) the startup of the application is something like 3.6 s (1350 ms for Swing and 2280 ms for spring context in lazy mode) and the memory usage is 8 mo. When you use the same GUI with @Configurable (with the spring agent) with the aop.xml the startup of the application is something like 2.4 s (800 ms for Swing and 1500 ms for spring context in lazy mode) and the memory usage is 5.1 mo. To sum up, GUI with ServiceLocator GUI with agent GUI with agent and aop.xml Startup Time 900 ms 3600 ms 2400 ms Memory 1.2 mo 5.1 mo 8.3 mo The aop.xml improves the performance and memory usage but not a lot compared to the version without agent (notably the memory is very problematic)
        Hide
        Michael Isvy added a comment -

        Also, Ramnivas was talking about wide use of LTW. Alexandre, as far as I can remember, you did all your testing with some pretty small applications isn't it?
        So I'm not sure it could be due to the fact that AspectJ parses too many classes (especialy for the high memory part).

        Show
        Michael Isvy added a comment - Also, Ramnivas was talking about wide use of LTW. Alexandre, as far as I can remember, you did all your testing with some pretty small applications isn't it? So I'm not sure it could be due to the fact that AspectJ parses too many classes (especialy for the high memory part).
        Hide
        Ramnivas Laddad added a comment -

        Michael, by "wide" I meant more classes are exposed to the weaver (whether or not they get woven due to pointcut expression).

        Alexandre, can you tighten "fr..*" more? I assume that your Swing classes that carry @Configurable are limited to very few packages. Note that you can use || expression or even multiple <include> elements. For example:

        <include within="fr.app.ui1..* || fr.app.ui2..*"/>

        or

        <include within="fr.app.ui1..*/>
        <include within="fr.app.ui2..*/>

        Also note that weave-time weaving should work the best in your scenario (is there a reason you cannot use it?).

        Show
        Ramnivas Laddad added a comment - Michael, by "wide" I meant more classes are exposed to the weaver (whether or not they get woven due to pointcut expression). Alexandre, can you tighten "fr..*" more? I assume that your Swing classes that carry @Configurable are limited to very few packages. Note that you can use || expression or even multiple <include> elements. For example: <include within="fr.app.ui1..* || fr.app.ui2..*"/> or <include within="fr.app.ui1..*/> <include within="fr.app.ui2..*/> Also note that weave-time weaving should work the best in your scenario (is there a reason you cannot use it?).
        Hide
        Alexandre Navarro added a comment -

        I retried with

        <aspectj>
        <weaver>
        <include within="fr.TestFrame"/> <!-- make sure your @Configurable classes are selected by this, and if possible very little else -->
        </weaver>
        </aspectj>

        And I didn't have any improvement compared to <include within="fr..*"/> (I have a very few classes in fr in my sample).

        To respond to Mickael, my sample is effectively a very small application. When I developped a bigger application, the problem becomes very problematic notably for the memory and the startup time (as I described in the description of the issue).

        My last test seems to prove that the problem does not come from too many classes are exposed to the weaver.

        Show
        Alexandre Navarro added a comment - I retried with <aspectj> <weaver> <include within="fr.TestFrame"/> <!-- make sure your @Configurable classes are selected by this, and if possible very little else --> </weaver> </aspectj> And I didn't have any improvement compared to <include within="fr..*"/> (I have a very few classes in fr in my sample). To respond to Mickael, my sample is effectively a very small application. When I developped a bigger application, the problem becomes very problematic notably for the memory and the startup time (as I described in the description of the issue). My last test seems to prove that the problem does not come from too many classes are exposed to the weaver.
        Hide
        Alexandre Navarro added a comment -

        I made a mistake on my table of performance (inversion of 2 results)

        GUI with ServiceLocator GUI with agent GUI with agent and aop.xml
        Startup Time 900 ms 3600 ms 2400 ms
        Memory 1.2 mo 8.3 mo 5.1 mo

        Show
        Alexandre Navarro added a comment - I made a mistake on my table of performance (inversion of 2 results) GUI with ServiceLocator GUI with agent GUI with agent and aop.xml Startup Time 900 ms 3600 ms 2400 ms Memory 1.2 mo 8.3 mo 5.1 mo
        Hide
        Thomas Pasch added a comment -

        Dear Alexandre,

        perhaps you could turn on the debug log level for the spring stuff and check if the problem is similar to SPR-9542.

        Show
        Thomas Pasch added a comment - Dear Alexandre, perhaps you could turn on the debug log level for the spring stuff and check if the problem is similar to SPR-9542 .

          People

          • Assignee:
            Unassigned
            Reporter:
            Alexandre Navarro
            Last updater:
            Thomas Pasch
          • Votes:
            2 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Days since last comment:
              1 year, 33 weeks, 6 days ago