Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-6870

Cache by-type lookups in DefaultListableBeanFactory

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Minor
    • Resolution: Complete
    • Affects Version/s: 2.5.6
    • Fix Version/s: 3.2 M1
    • Component/s: Core
    • Labels:
    • Last commented by a User:
      true

      Description

      The Autowiring algorithms tries to work out the dependencies by building up the Beans. If this fails, a BeanCreationException is thrown, caught and then a different way to handle the dependencies is tried. In some situations this results in slow performance and it is probably also not the nicest programming style.

      1. SPR6870.patch
        3 kB
        Kristian Rosenvold
      2. perfDiffStockVsPatch1.html
        155 kB
        Kristian Rosenvold
      3. perf305stock.html
        121 kB
        Kristian Rosenvold
      4. perf305MainPatch.html
        110 kB
        Kristian Rosenvold

        Issue Links

          Activity

          Hide
          digulla Aaron Digulla added a comment -

          Any chance to see some work on this? The performance of looking up Spring beans by type is a bother for us as well.

          We solved this outside of Spring by using this workaround:

          getBean(Class<T> type) {
              String name = type.getName() + "#0";
              return getBean( name, type );
          }

          The idea is that for most singletons, there is only a single implementation, so the ID can be omitted and Spring will use the type of the bean to generate a name. This means that you need to do some extra work for interfaces or that you must always request beans using interface by a specific ID and never by type.

          But it's a poor solution. It's pretty simple to cache the bean definition lookup in getBean(Class<T> type) and that would give a huge performance boost without the need for any hacks.

          Show
          digulla Aaron Digulla added a comment - Any chance to see some work on this? The performance of looking up Spring beans by type is a bother for us as well. We solved this outside of Spring by using this workaround: getBean(Class<T> type) { String name = type.getName() + "#0"; return getBean( name, type ); } The idea is that for most singletons, there is only a single implementation, so the ID can be omitted and Spring will use the type of the bean to generate a name. This means that you need to do some extra work for interfaces or that you must always request beans using interface by a specific ID and never by type. But it's a poor solution. It's pretty simple to cache the bean definition lookup in getBean(Class<T> type) and that would give a huge performance boost without the need for any hacks.
          Show
          mindas Mindaugas Žakšauskas added a comment - Spring, please solve this. Here's my story: http://stackoverflow.com/questions/9429612/spring-wiring-by-type-is-slower-by-magnitude-than-wiring-by-name
          Hide
          youngm Mike Youngstrom added a comment -

          I've been told this is a risky fix because it is right in the core of some complex code. NOW is the perfect time attempt to fix this since you are so early in the 3.2 release cycle!

          Show
          youngm Mike Youngstrom added a comment - I've been told this is a risky fix because it is right in the core of some complex code. NOW is the perfect time attempt to fix this since you are so early in the 3.2 release cycle!
          Hide
          cbeams Chris Beams added a comment -

          Thanks, Kristian for the patch. With minor modifications, it has been applied and indeed solves the problem nicely.

          At the time of this writing the snapshot containing these changes has just finished publishing. There are a large number of watchers on this issue – please consider taking the latest 3.2.0.BUILD-SNAPSHOT for a spin and provide any feedback. Note that we'll be shipping this change with 3.2 M1 within a day or two as well; but naturally any feedback prior to that would be great.

          commit 4c7a1c0a5403b35dd812dae1f2a753538928bb32 (HEAD, SPR-6870)
          Author: Chris Beams <[email protected]>
          Date:   Sun May 27 17:40:33 2012 +0300
           
              Cache by-type lookups in DefaultListableBeanFactory
           
              Prior to this change, by-type lookups using DLBF#getBeanNamesForType
              required traversal of all bean definitions within the bean factory
              in order to inspect their bean class for assignability to the target
              type. These operations are comparatively expensive and when there are a
              large number of beans registered within the container coupled with a
              large number of by-type lookups at runtime, the performance impact can
              be severe. The test introduced here demonstrates such a scenario clearly.
              
              This performance problem is likely to manifest in large Spring-based
              applications using non-singleton beans, particularly request-scoped
              beans that may be created and wired many thousands of times per second.
              
              This commit introduces a simple ConcurrentHashMap-based caching strategy
              for by-type lookups; container-wide assignability checks happen only
              once on the first by-type lookup and are afterwards cached by type
              with the values in the map being an array of all bean names assignable
              to that type. This means that at runtime when creating and autowiring
              non-singleton beans, the cost of by-type lookups is reduced to that of
              ConcurrentHashMap#get.
              
              Issue: SPR-6870

          Show
          cbeams Chris Beams added a comment - Thanks, Kristian for the patch. With minor modifications, it has been applied and indeed solves the problem nicely. At the time of this writing the snapshot containing these changes has just finished publishing. There are a large number of watchers on this issue – please consider taking the latest 3.2.0.BUILD-SNAPSHOT for a spin and provide any feedback. Note that we'll be shipping this change with 3.2 M1 within a day or two as well; but naturally any feedback prior to that would be great. commit 4c7a1c0a5403b35dd812dae1f2a753538928bb32 (HEAD, SPR-6870) Author: Chris Beams <[email protected]> Date: Sun May 27 17:40:33 2012 +0300   Cache by-type lookups in DefaultListableBeanFactory   Prior to this change, by-type lookups using DLBF#getBeanNamesForType required traversal of all bean definitions within the bean factory in order to inspect their bean class for assignability to the target type. These operations are comparatively expensive and when there are a large number of beans registered within the container coupled with a large number of by-type lookups at runtime, the performance impact can be severe. The test introduced here demonstrates such a scenario clearly. This performance problem is likely to manifest in large Spring-based applications using non-singleton beans, particularly request-scoped beans that may be created and wired many thousands of times per second. This commit introduces a simple ConcurrentHashMap-based caching strategy for by-type lookups; container-wide assignability checks happen only once on the first by-type lookup and are afterwards cached by type with the values in the map being an array of all bean names assignable to that type. This means that at runtime when creating and autowiring non-singleton beans, the cost of by-type lookups is reduced to that of ConcurrentHashMap#get. Issue: SPR-6870
          Hide
          sylvain.laurent Sylvain LAURENT added a comment -

          For those watching this issue, it has ben back ported to 3.1.2, see SPR-9448

          Show
          sylvain.laurent Sylvain LAURENT added a comment - For those watching this issue, it has ben back ported to 3.1.2, see SPR-9448

            People

            • Assignee:
              cbeams Chris Beams
              Reporter:
              eberhardwolff Eberhard Wolff
              Last updater:
              Sylvain LAURENT
            • Votes:
              45 Vote for this issue
              Watchers:
              45 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                5 years, 2 weeks, 5 days ago

                Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - Not Specified
                Not Specified
                Logged:
                Time Spent - 3.5h
                3.5h