java位元組碼框架效能對比
阿新 • • 發佈:2019-02-14
因為專案需要用到動態代理,糾結於jdk原生代理,cglib和spring包裝過的cglib,以及javassist和byte code javassist之間的技術選型。所以寫個test case,測試他們之間的效能差異。話不多說,上程式碼。
package proxy; import javassist.*; import javassist.util.proxy.MethodHandler; import javassist.util.proxy.ProxyFactory; import javassist.util.proxy.ProxyObject; import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.text.DecimalFormat; /** * Created by qinpr on 18/6/6. */ public classDynamicProxyTest { public static void main(String[] args) throws Exception { CountServiceImpl delegatge = new CountServiceImpl(); long time = System.currentTimeMillis(); CountService jdkDynamicProxy = createJdkDynamicProxy(delegatge); System.out.println("Create JDK Proxy : " + (System.currentTimeMillis() - time) + " ms"); time = System.currentTimeMillis(); CountService cglibDynamicProxy = createCglibDynamicProxy(delegatge); System.out.println("Create CGLIB Proxy : " + (System.currentTimeMillis() - time) + " ms"); time = System.currentTimeMillis(); CountService springCglibDynamicProxy = createSpringCglibDynamicProxy(delegatge); System.out.println("Create Spring CGLIB Proxy : " + (System.currentTimeMillis() - time) + " ms"); time = System.currentTimeMillis(); CountService javassistProxy = createJavassistDynamicProxy(delegatge); System.out.println("Create JAVASSIST Proxy : " + (System.currentTimeMillis() - time) + " ms"); time = System.currentTimeMillis(); CountService javassitBytecodeProxy = createJavassistBytecodeDynamicProxy(delegatge); System.out.println("Create JAVASSIST Bytecode Proxy : " + (System.currentTimeMillis() - time) + " ms"); System.out.println("---------------------------------------------"); for (int i=0 ; i < 1; i++) { test(jdkDynamicProxy, "Run jdk proxy: "); test(cglibDynamicProxy, "Run cglib proxy: "); test(springCglibDynamicProxy, "Run spring cglib proxy: "); test(javassistProxy, "Run javassist proxy: "); test(javassitBytecodeProxy, "Run javassist bytecode proxy: "); } } private static CountService createJdkDynamicProxy(final CountService delegate) { CountService jdkProxy = (CountService) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{CountService.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(delegate, args); } }); return jdkProxy; } private static CountService createCglibDynamicProxy(final CountService delegate) throws Exception { Enhancer enhancer = new Enhancer(); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { return method.invoke(delegate, args); } }); enhancer.setInterfaces(new Class[]{CountService.class}); CountService proxy = (CountService) enhancer.create(); return proxy; } private static CountService createSpringCglibDynamicProxy(final CountService delegate) throws Exception { org.springframework.cglib.proxy.Enhancer springEnhancer = new org.springframework.cglib.proxy.Enhancer(); springEnhancer.setCallback(new org.springframework.cglib.proxy.MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] args, org.springframework.cglib.proxy.MethodProxy methodProxy) throws Throwable { return method.invoke(delegate, args); } }); springEnhancer.setInterfaces(new Class[]{CountService.class}); CountService proxy = (CountService) springEnhancer.create(); return proxy; } private static CountService createJavassistDynamicProxy(final CountService delegate) throws Exception { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setInterfaces(new Class[]{CountService.class}); Class proxyClass = proxyFactory.createClass(); CountService javassistProxy = (CountService) proxyClass.newInstance(); ((ProxyObject)javassistProxy).setHandler(new MethodHandler() { @Override public Object invoke(Object o, Method method, Method method1, Object[] args) throws Throwable { return method.invoke(delegate, args); } }); return javassistProxy; } private static CountService createJavassistBytecodeDynamicProxy(CountService delegate) throws Exception { ClassPool mPool = new ClassPool(true); CtClass mCtc = mPool.makeClass(CountService.class.getName() + "JavaassistProxy"); mCtc.addInterface(mPool.get(CountService.class.getName())); mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc)); mCtc.addField(CtField.make("public " + CountService.class.getName() + " delegate;", mCtc)); mCtc.addMethod(CtNewMethod.make("public int count() { return delegate.count(); }", mCtc)); Class pc = mCtc.toClass(); CountService byteCodeProxy = (CountService) pc.newInstance(); Field filed = byteCodeProxy.getClass().getField("delegate"); filed.set(byteCodeProxy, delegate); return byteCodeProxy; } public static void test(CountService service, String label) { service.count(); int count = 10000000; long time = System.currentTimeMillis(); for (int i=0; i < count ; i++) { service.count(); } time = System.currentTimeMillis() - time; System.out.println(label + time + " ms," + new DecimalFormat().format(count * 1000 / time) + " t/s"); } public static interface CountService { int count(); } public static class CountServiceImpl implements CountService { private int count = 0; @Override public int count() { return count ++; } } }
測試結果:在生成代理過程中jkd完勝15ms,傳說中的cglib最慢。在迴圈呼叫100萬次後,byte code javassiste完勝。
Connected to the target VM, address: '127.0.0.1:61663', transport: 'socket'
Create JDK Proxy : 15 ms
Create CGLIB Proxy : 225 ms
Create Spring CGLIB Proxy : 176 ms
Create JAVASSIST Proxy : 73 ms
Create JAVASSIST Bytecode Proxy : 105 ms
---------------------------------------------
Run jdk proxy: 181 ms,7,790,416 t/s
Run cglib proxy: 392 ms,3,597,105 t/s
Run spring cglib proxy: 456 ms,3,092,248 t/s
Run javassist proxy: 554 ms,2,545,244 t/s
Run javassist bytecode proxy: 42 ms,33,572,985 t/s