1 2 Previous Next 23 Replies Latest reply on Apr 17, 2004 8:05 AM by spiritualmechanic

    object pooling detrimental to performance

    bill.burke

      FYI:

      Did some tests in AOP framework with object pooling through a ThreadLocal. I found that it actually slowed down performance by 20%. This finalizes what I've thought all along that Object pooling is worthless and it is better to let the VM handle it.

      Here's what I implemented:

      public class MethodInvocation extends Invocation
      {
       public Object[] arguments = null; // MARSHALLED
       public transient Method method = null;
       public long methodHash;
      
       public MethodInvocation(org.jboss.aop.advice.Interceptor[] interceptors)
       {
       super(InvocationType.METHOD, interceptors);
       }
      
       protected void clear()
       {
       super.clear();
       arguments = null;
       }
      
       public static class Pool
       {
      
       private ThreadLocal pool = new ThreadLocal();
      
       public MethodInvocation getInstance(Interceptor[] interceptors)
       {
       MethodInvocation[] pooled = (MethodInvocation[]) pool.get();
       if (pooled == null)
       {
       System.out.println("returning new invocation");
       return new MethodInvocation(interceptors);
       }
       MethodInvocation instance = null;
       for (int i = pooled.length - 1; i >= 0; i--)
       {
       if (pooled == null) continue;
       instance = pooled;
       pooled = null;
       break;
       }
       if (instance == null)
       {
       System.out.println("returning new invocation");
       return new MethodInvocation(interceptors);
       }
       instance.interceptors = interceptors;
       return instance;
       }
      
       public void releaseInstance(MethodInvocation invocation)
       {
       invocation.clear();
       MethodInvocation[] pooled = (MethodInvocation[]) pool.get();
       if (pooled == null)
       {
       pooled = new MethodInvocation[1];
       pooled[0] = invocation;
       pool.set(pooled);
       return;
       }
       int i = 0;
       for (; i < pooled.length; i++)
       {
       if (pooled == null)
       {
       pooled = invocation;
       return;
       }
       }
       // pool is too big
       MethodInvocation[] newPooled = new MethodInvocation[pooled.length + 1];
       System.arraycopy(pooled, 0, newPooled, 0, pooled.length);
       newPooled[pooled.length] = invocation;
       pool.set(newPooled);
      
       }
       }
      
       }
      


        • 1. Re: object pooling detrimental to performance
          marc.fleury

          wow, quite interesting.

          • 2. Re: object pooling detrimental to performance
            rythos

            The intention of this code is to reuse MethodInvocation objects? Is it that costly to build them normally?

            • 3. Re: object pooling detrimental to performance
              bill.burke

              It is not costly to build Invocation objects (field, method, caller, etc...) as it is only a bunch of field sets.

              • 4. Re: object pooling detrimental to performance
                rythos

                I thought object pooling was a good idea when creating the object was costly? If creating MethodInvocations isn't a performance hit, why were you trying to pool them?

                • 5. Re: object pooling detrimental to performance
                  marc.fleury

                  That is kind of interesting really. People where bitching about the hit they were taking with the object creation. I find it hard to believe that in fact it is FASTER to not pool. Very interesting. I guess the limit is VM garbage collection on large system vs pooling. Meaning in the future we should think about it in the scope of scalability.

                  But for now people are going to bench invocations one by one so this number is better

                  • 6. Re: object pooling detrimental to performance

                    I would say that this is because the MethodInvocations aren't hard referenced
                    for very long. The GC can easily dispose of short lived references.

                    If you try to pool them, you are making more work for the GC because the objects
                    need to be continually checked.

                    The latest GCs do object pooling anyway for frequently used object types.
                    Let the JIT decide what objects need to be pooled.
                    It can will do a better job anyway - you can make mistakes by not reinitialising objects
                    correctly.

                    FYI: I recently got rid of the object pooling in jbossmq. Not only was it
                    unnecessary, it made the implementation more brittle.
                    The message cache had to be very careful about when and what message
                    object it was reusing. Very error prone for any developers who weren't aware of the
                    pooling semantics.

                    Like the poster said above, you only need pool when there are significant resources
                    like threads or jdbc connections that make constructing the object slow.

                    Regards,
                    Adrian

                    • 7. Re: object pooling detrimental to performance
                      marc.fleury

                      tell bill and I about "brittleness" of pools.

                      the entity pooling was A NIGHTMARE to debug back in the days. The state in them was always difficult to control, cleanup was a nightmare. WE finally decided to drop it there in favor of pools that just "preinstanciated" but when an object was done we would let it die, in short we would not use pools for "reuse" at all.

                      Also the VM insight you give is probably linked to generational garbage collection, obviously the VM has to work on new references but never promotes them to "long lived" so it can be pretty efficient in killing newly instanciated object that are short lived <1s like the invocation object.

                      So the only idea that would stand is to pre-create objects and do setters on them so it is really fast. Bill is that what you mean when you say we are already doing sets?

                      • 8. Re: object pooling detrimental to performance
                        rythos

                        Read an article today on HotSpot optimization that says basically the same thing you said about object pooling. On page 6:

                        For example, the HotSpot development team strongly recommends that you not maintain your own object pools. Instead, you should trust the memory allocation and garbage collection system to work efficiently.



                        Article URL:
                        http://www.fawcette.com/javapro/2002_10/magazine/columns/proshop/default.aspx

                        • 9. Re: object pooling detrimental to performance
                          bill.burke

                          I have heard different things from different people. My thought was always that the VM was better than pooling, but I've had people argue for (and code) pooling. So I just went and found out for myself

                          • 10. Re: object pooling detrimental to performance
                            marc.fleury

                            One more thing that will throw off HotSpot is the Advisable interface since it essentially says that the profile of a method changes in time. There need to be callbacks on insertion of interceptors to retrigger compilation

                            • 11. Re: object pooling detrimental to performance
                              bill.burke

                              That's not the way JBoss AOP works. There will be no problem with HotSpot as you describe.

                              • 12. Re: object pooling detrimental to performance
                                marc.fleury

                                what part of JBossAOP doesn't work like what I said, explain that to me, you mean there is no advisable interface? we certainly show it in slides.

                                Essentially the method stack isn't set in time and therefore optimizations would be thrown off... what are you talking about?

                                • 13. Re: object pooling detrimental to performance
                                  bill.burke

                                  Ok, went even further and simplified...Still pooling was 15% slower.

                                   private static final ThreadLocal pool = new ThreadLocal();
                                  
                                   public static MethodInvocation create(Interceptor[] chain)
                                   {
                                   MethodInvocation mi = (MethodInvocation) pool.get();
                                   if (mi == null) return new MethodInvocation(chain);
                                   mi.interceptors = chain;
                                   return mi;
                                   }
                                  
                                   public static void release(MethodInvocation mi)
                                   {
                                   mi.metadata = null;
                                   mi.currentInterceptor = 0;
                                   mi.interceptors = null;
                                   mi.instanceResolver = null;
                                   mi.contextResolver = null; // field/method metadata
                                   mi.classResolver = null; // field/method metadata
                                   mi.targetObject = null;
                                   mi.arguments = null;
                                   mi.method = null;
                                   mi.actualMethod = null;
                                   pool.set(mi);
                                  
                                   }
                                  


                                  • 14. Re: object pooling detrimental to performance

                                    Very interesting.

                                    1 2 Previous Next