Discussions

News: Why do you think CGLib proxies are faster than JDK Proxies?

  1. It's fairly common knowledge that CGLib provides a proxy mechanism that is faster than the JDK's built in proxying mechanism. Or is it more of an Urban myth? I decided I was going to be a good citizen and wanted a mechanism where I could quickly switch between JDK proxies and CGLib proxies in a manner similar to the way AOP frameworks typically make this a small configuration change. I found just such a package in oranjestad commons proxy class. What caught my attention was the performance note at the bottom, where the author indicates that in his testing he actually found JDK proxies faster. My first assumption was that this was due to poor implementation on his part but it got me thinking. I had actually never attempted to validate this urban myth before. So a quick search on the web yielded several links that suggested CGLib is faster (most are older):One article actually provides code (independent of the Oranjestad commons proxy):Implement Your Own Proxy-Based AOP Framework. I downloaded the this code and ran it myself. The output on my developer class laptop (IBM ThinkPad T43, Intel 2.0 GHz, 2 GBytes of RAM) was as follows:08:49:21,093 INFO [DefaultAopProxyFactory] CGLIB2 available: proxyTargetClass feature enabled 08:49:21,109 INFO [CollectionFactory] JDK 1.4+ collections available 08:49:21,109 INFO [CollectionFactory] Commons Collections 3.x available Unproxied: 559009(ns) 5(ms) cglib: 21374225(ns) 213(ms) Proxy: 16506009(ns) 165(ms)This seems totally consistent with the Oranjestad performance test. So why do we all think CGlib has faster proxies?

    Threaded Messages (23)

  2. interesting, thanks.
  3. In my testing, the bytecode proxies (using Javassist, not CGLIB) were only marginally faster than dynamic proxies; the different I saw was in memory utilization, since lots of tiny arrays (for method parameters) need to be created for dynamic proxies. However, that was a couple of JDKs ago so everything will have changed.
  4. What JDK, CGLib version?[ Go to top ]

    Well, probably proxy implementation improved in JDK 5 & 6 I remember that in my tests CGLib 1 was measurable faster then CGLib 2. I first used CGLib 1 with JDK 4, but can't remember that I compared CGLib and JDK proxy for performance. But generally, in JDK proxy you write your method resolution code (typicaly by comparing strings), while in most cases CGLib provides you with method resolution in auto-generated byte code, which can usually be direct method call without anything else.
  5. speed is not the only reason[ Go to top ]

    When I use CGLIB (as opposed to JDK Proxy) speed is not the only criterion. One thing that I like about CGLIB is that you can proxy classes and not just interfaces as in the JDK's proxy.
  6. Re: speed is not the only reason[ Go to top ]

    One thing that I like about CGLIB is that you can proxy classes and not just interfaces as in the JDK's proxy.
    Indeed. That's the reason CGLIB is used in Spring AOP (abstracted away from the user, to simplify and allow for other implementation choices in future). If you only want to proxy interfaces, dynamic proxies just come with the language and work great. Any performance difference should be pretty minor if you're on anything but a very old JVM (1.3 vintage). Rgds Rod
  7. I have realized significant difference in performance metrics when the non-singleton bean(prototype bean) is injected into a non-singleton OR singleton bean using setter(or property) injection and lookup method. Note: myDAOImpleBean is also prototype bean The injected prototype beans injects few more beans. In total, there are around 15-20 beans instantiated when getService() is being called on myBean. So the question is, The later approach(property injection) is taking around 500ms to create and inject the beans where as the formaer approach(lookup-method) is taking around 30ms. Significant difference...I dont find anything in Spring Docs on this topic. Wondering whether anyone of you ran into same/similar issue?
  8. Cglib is definitely faster[ Go to top ]

    I suspect you're including the proxy creation in your test and using code like this to create your cglib proxy? Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(methodInterceptor); return (T)enhancer.create(); If you're concerned about performance, whether you're using cglib or dynamic proxies, you should hold onto the proxy class and use that to create proxies instead. See the cglib-based method interception code in Guice for an example. What matters is that cglib is faster for method interception. You only get one handler per object with dynamic proxies, which means you typically have to do at least one map lookup per method invocation. Cglib, on the other hand, lets you use separate handler for each method. This means no map lookups, and if you're not actually intercepting a method, no unnecessary overhead.
  9. Cglib is NOT definitly faster[ Go to top ]

    I suspect you're including the proxy creation in your test and using code like this to create your cglib
    The code is available in the links and does not include creation part in the timing as you suggest. Java Proxies are faster. If you need to intercept with classes then CGLib makes sense since proxies can't do this, but I won't accept people saying CGLib is faster until they provide code proving it.
  10. I suspect you're including the proxy creation in your test and using code like this to create your cglib


    The code is available in the links and does not include creation part in the timing as you suggest.

    Java Proxies are faster. If you need to intercept with classes then CGLib makes sense since proxies can't do this, but I won't accept people saying CGLib is faster until they provide code proving it.
    Didn't Crazy Bob provide a link to his code -- http://google-guice.googlecode.com/svn/trunk/src/com/google/inject/ProxyFactory.java ? Are you saying that his code sample is NOT valid for your needs ? Thank you, BR, ~A
  11. Didn't Crazy Bob provide a link to his code --
    Yes he did, and when I executed it i found that Java proxies are faster. The point of the article is not to read someone else's results and accept their conclusions, it's to take the examples and verify for yourself.
  12. Is there a difference in the hardware like CPU? peter
  13. Re: could it be differences in hardware?[ Go to top ]

    Is there a difference in the hardware like CPU?
    No, Cglib really is faster, unless of course you're lucky enough to have a proxy which returns the exact same value every time regardless of the method. ;)
  14. How about this[ Go to top ]

    Maybe what would be helpful is for you to explain why the code links in the article runs slower. You answered my question by sending me completely new code. The code referenced in the article *claims* that GGLib is faster, then when you download it... it is slower. So I'd be curious why that code runs slower. I could download your code, but you are getting into the guts of CGLib and I was hoping for a simple interface.
  15. Re: could it be differences in hardware?[ Go to top ]

    Is there a difference in the hardware like CPU?
    No, Cglib really is faster, unless of course you're lucky enough to have a proxy which returns the exact same value every time regardless of the method. ;)
    So if I understand correctly, it runs faster for you, but not for someone else. Same code should run the same assuming the hardware is similar enough. If there's a difference, then it must be something causing it. peter
  16. Re: could it be differences in hardware?[ Go to top ]

    So if I understand correctly, it runs faster for you, but not for someone else. Same code should run the same assuming the hardware is similar enough. If there's a difference, then it must be something causing it.

    peter
    We didn't run the same code. Prodeep ran the code from the Javadocs he linked to in the original post, but that test isn't very realistic. I provided a different test (pasted above) which illustrates one of the places where cglib is faster.
  17. Ah..It's the old bait and switch. First you have to prove the theory incorrect and then you get suckered in to providing a full tutorial on all technologies used in the original question posed.
    ....We didn't run the same code. Prodeep ran the code from the Javadocs he linked to in the original post, but that test isn't very realistic. I provided a different test (pasted above) which illustrates one of the places where cglib is faster.
  18. Re: could it be differences in hardware?[ Go to top ]

    So if I understand correctly, it runs faster for you, but not for someone else. Same code should run the same assuming the hardware is similar enough. If there's a difference, then it must be something causing it. peter
    We didn't run the same code. Prodeep ran the code from the Javadocs he linked to in the original post, but that test isn't very realistic. I provided a different test (pasted above) which illustrates one of the places where cglib is faster.
    ok, that makes more sense. But that still doesn't help others figure out when cglib is faster and slower than java proxy. peter
  19. Seems like CGLib is faster[ Go to top ]

    Well, I was googling to find out which one was faster and landed up on this thread. I ran the example provided by Bob and in my machine, CGLib is faster than JDK Proxy. I used CGLib 2.2 / Java 1.6_05 on Windows XP SP2 (Core Duo 2GHz / 1GB RAM) The result of execution was this : JDK Proxy: 959,881 calls/s CGLIB: 2,504,556 calls/s
  20. Well, I was googling to find out which one was faster and landed up on this thread. I ran the example provided by Bob and in my machine, CGLib is faster than JDK Proxy
    Same here, on 2 different VMs: Sun HotSpot Server 1.5.0_16-b02, mixed mode): JDK Proxy: 2,937,636 calls/s CGLIB: 6,184,497 calls/s Sun (build 1.6.0_07-b06) HotSpot Server (build 10.0-b23, mixed mode): JDK Proxy: 1,902,922 calls/s CGLIB: 3,551,802 calls/s JDK Proxy: 3,256,502 calls/s CGLIB: 5,778,956 calls/s Platform used: Linux 2.6.25-2-686 Debian Lenny, on Dell Precision 390, Core 2 6300@1.86Ghz
  21. Re: Cglib is NOT definitly faster[ Go to top ]

    Java Proxies are faster. If you need to intercept with classes then CGLib makes sense since proxies can't do this, but I won't accept people saying CGLib is faster until they provide code proving it.
    I'm sorry, but Cglib is faster. I pasted an example below. Here's the final result with the "-client" JVM option: JDK Proxy: 693,588 calls/s CGLIB: 1,895,249 calls/s The two are closer with the "-server" option, but cglib is still faster: JDK Proxy: 4,462,232 calls/s CGLIB: 5,551,438 calls/s As I pointed out in my first message, cglib will be even faster in real world situations because it supports having a separate handler for each method. public class ProxyPerformanceComparison { public static void main(String[] args) throws Exception { Callable jdkProxy = (Callable) Proxy.newProxyInstance( ClassLoader.getSystemClassLoader(), new Class[] { Callable.class }, new JdkHandler(new Counter()) ); Enhancer enhancer = new Enhancer(); enhancer.setCallback(new CglibInterceptor(new Counter())); enhancer.setInterfaces(new Class[] { Callable.class }); Callable cglibProxy = (Callable) enhancer.create(); for (int i2 = 0; i2 < 10; i2++) { iterate(jdkProxy, "JDK Proxy: "); iterate(cglibProxy, "CGLIB: "); System.err.println(); } } static final DecimalFormat format = new DecimalFormat(); static void iterate(Callable callable, String label) throws Exception { int count = 10000000; long time = System.currentTimeMillis(); int total = 0; for (int i = 0; i < count; i++) { total += callable.call(); } time = System.currentTimeMillis() - time; System.err.println(label + format.format(count * 1000 / time) + " calls/s"); } static class JdkHandler implements InvocationHandler { final Object delegate; JdkHandler(Object delegate) { this.delegate = delegate; } public Object invoke(Object object, Method method, Object[] objects) throws Throwable { return method.invoke(delegate, objects); } } static class CglibInterceptor implements MethodInterceptor { final Object delegate; CglibInterceptor(Object delegate) { this.delegate = delegate; } public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invoke(delegate, objects); } } static class Counter implements Callable { int count = 0; public Integer call() throws Exception { return count++; } } }
  22. Use ASM instead of CGLIB[ Go to top ]

    If you care about performance so much you should consider using ASM instead of CGLIB. It's much harder (it looks like Assembler ;) but you gain full control of loading your classes. Of course you will encounter other problems but it will pay most probably.
  23. That is why people prefer CGLIB over ASM. CGLIB basically allow you to code on plain Java without any need to learn Java bytecode. Said that, it doesn't mean that we couldn't create some reusable abstraction for creating proxies in ASM (we already have generic adapter to intercept method entry and exit points)...
  24. In case anone is interested, there is a library called Jakarta Commons Proxy (it's in the sandbox) that allows you to easily switch between JDK, CGLIB, and Javassist for your proxying technology. It might be useful in benchmarking these technologies against one another. http://jakarta.apache.org/commons/sandbox/proxy/