• “两学一做”在山西——黄河新闻网 2019-07-13
  • 内地生报读香港高校本科人数持续下跌 2019-07-13
  • 【学习时刻】人民大学王义桅:金砖合作的“自信”与“自觉” 2019-07-12
  • 女子请“私家侦探”被骗3万 警方循线捣毁诈骗团伙 2019-07-11
  • 【学习时刻】北交大马院院长韩振峰:高校思想政治工作必须牢牢把握三大根本问题 2019-07-11
  • 全国“非遗”保护工作先进名单公布 2019-07-01
  • 紫光阁中共中央国家机关工作委员会 2019-06-25
  • 杭州控烟令修改草案拟允许室内设吸烟区,控烟专家:跌破眼镜 2019-06-25
  • 挪用近30万报纸征订款赌博 河南一报社聘用制干部获刑 2019-06-23
  • 2016年,有1145家上市公司大小非减持了3600亿元,还有210名上市公司高管减持了1400亿元。IPO已成了造就成千上万个十亿、百亿富豪的捷径, 2019-06-21
  • 专家“把脉”中国电影市场:提升品质方能逆袭 2019-06-21
  • “善款资助副局长儿子留学”真相须尽快落地 2019-06-19
  • 21岁女护士失联2天后确认遇害 嫌疑人为其前男友 2019-06-19
  • 中国地质公园名录旅行地中国国家地理网 2019-06-13
  • 玄关运用有四大原则 用的好才能财旺挡煞聚财 ——凤凰网房产 2019-06-10
  • Jmh测试JDK,CGLIB,JAVASSIST动态代理方式的性能

    广东十一选5一定牛 www.aavbg.com  

    前言

    JDK,CGLIB,JAVASSIST是常用的动态代理方式。

    JDK动态代理仅能对具有接口的类进行代理。

    CGLIB动态代理方式的目标类可以没有接口。

    Javassist是一个开源的分析、编辑和创建Java字节码的类库,JAVASSIST可以动态修改类,比如添加方法和属性。JAVASSIST的目标类也没有接口限制。

    动态代理常用在RPC接口调用中,因此选择一个好的动态代理方式,会对系统性能有一定的提升。

     

    对于代码的性能测试,常规的方法如下,如此是无法获取到准确的性能数据的

    long start = System.currentTimeMillis();
    xxx.xx();
    long end = System.currentTimeMillis();
    System.out.println("运行时间:"+(end-start));

     

    JMH用来做基准测试,由于JIT编译器会根据代码运行情况进行优化,代码在第一次执行的时候,速度相对较慢,随着运行的次数增加,JIT编译器会对代码进行优化,以达到最佳的性能状态。

    JMH可以对代码进行预热,让代码达到最佳的性能状态,再进行性能测试。

    更详细的说明参考: 使用JMH做Benchmark基准测试

     

    本博客主要讲解使用JMH对这三种动态代理的对象创建过程和方法调用进行测试。JDK版本是8.0.

    代理实现

    Jdk方式

    public class JdkInvocationHandler  implements InvocationHandler {
    
        private Object target = null;
        public JdkInvocationHandler(Object object){
            this.target = object;
        }
    
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            Object result = method.invoke(this.target,args);
            return result;
        }
    
        public  Object getProxy(){
            Object object =    Proxy.newProxyInstance(
                    this.target.getClass().getClassLoader(),
                    this.target.getClass().getInterfaces(),
                    this);
            return  object;
        }
    
    }

     

    Cglib方式

    引入pom

         <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.2.5</version>
            </dependency>

     

    代码

    public class CglibProxy  implements MethodInterceptor {
    
        private Enhancer enhancer = new Enhancer();
    
        public  Object getProxy(Class clazz){
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
            return enhancer.create();
    
        }
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
            Object result = methodProxy.invokeSuper(o,objects);
    
            return result;
        }
    }

     

    Javassist方式

    pom

        <dependency>
                <groupId>org.openjdk.jmh</groupId>
                <artifactId>jmh-core</artifactId>
                <version>1.20</version>
                <scope>compile</scope>
            </dependency>
    
            <dependency>
                <groupId>org.openjdk.jmh</groupId>
                <artifactId>jmh-generator-annprocess</artifactId>
                <version>1.20</version>
            </dependency>

     

    代码

    public class JavassistProxy {
    
        public <T> T getProxy(Class<T> interfaceClass){
            ProxyFactory proxyFactory  = new ProxyFactory();
    
            if(interfaceClass.isInterface()){
                Class[] clz  = new Class[1];
                clz[0] = interfaceClass;
                proxyFactory.setInterfaces(clz);
            }
            else {
                proxyFactory.setSuperclass(interfaceClass);
            }
            proxyFactory.setHandler(new MethodHandler() {
                public Object invoke(Object proxy, Method method, Method method1, Object[] args) throws Throwable {
                    Object result = method1.invoke(proxy,args);
                    return  result;
                }
            });
            try{
                T bean =  (T)proxyFactory.createClass().newInstance();
                return  bean;
            }
            catch(Exception ex){
                log.error("Javassit 创建代理失败:{}",ex.getMessage());
                return null;
            }
        }
    
    }

     

    性能测试

    创建性能测试

    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.NANOSECONDS)
    public class ProxyCreateTest {
    
        public static void main(String args[]) throws Exception{
    
            Options ops = new OptionsBuilder().include(ProxyCreateTest.class.getSimpleName())
                    .forks(1).build();
            new Runner(ops).run();
        }
    
        @Benchmark
        public void CglibProxyCreate(){
            ProxyService proxyService =  (ProxyService)new CglibProxy().getProxy(ProxyServiceImpl.class);
        }
    
    
       @Benchmark
        public void JdkProxyCreate(){
           ProxyService proxyService = (ProxyService) new JdkInvocationHandler(new ProxyServiceImpl()).getProxy();
        }
    
        @Benchmark
        public void JavassistProxyCreate(){
            ProxyService proxyService = (ProxyService)  new JavassistProxy().getProxy(ProxyServiceImpl.class);
        }
    
    }

     

     测试结果

      第一次测试
    * Benchmark Mode Cnt Score Error Units * ProxyCreateTest.CglibProxyCreate avgt 20 192.691 ± 5.962 ns/op * ProxyCreateTest.JavassistProxyCreate avgt 20 2741254.026 ± 334384.484 ns/op * ProxyCreateTest.JdkProxyCreate avgt 20 130.982 ± 14.467 ns/op * * 第二次测试 * Benchmark Mode Cnt Score Error Units * ProxyCreateTest.CglibProxyCreate avgt 20 212.150 ± 15.399 ns/op * ProxyCreateTest.JavassistProxyCreate avgt 20 2995729.108 ± 265629.897 ns/op * ProxyCreateTest.JdkProxyCreate avgt 20 124.842 ± 8.404 ns/op *
    第三次测试 * Benchmark Mode Cnt Score Error Units * ProxyCreateTest.CglibProxyCreate avgt 20 206.603 ± 6.834 ns/op * ProxyCreateTest.JavassistProxyCreate avgt 20 2979335.282 ± 290935.626 ns/op * ProxyCreateTest.JdkProxyCreate avgt 20 129.260 ± 9.020 ns/op

     

    从测试结果来看,javassist的代理对象创建性能最差。最好的是JDK方式。

    调用性能测试

    //所有测试线程共享一个实例
    @State(Scope.Benchmark)
    //调用的平均时间,例如“每次调用平均耗时xxx毫秒”,单位是时间/操作数 @BenchmarkMode(Mode.AverageTime)
    //单位为纳秒 @OutputTimeUnit(TimeUnit.NANOSECONDS)
    public class ProxyRunTest { private ProxyService proxyServiceCglib = (ProxyService)new CglibProxy().getProxy(ProxyServiceImpl.class); private ProxyService proxyServiceJdk = (ProxyService) new JdkInvocationHandler(new ProxyServiceImpl()).getProxy(); private ProxyService proxyServiceJavassist = (ProxyService) new JavassistProxy().getProxy(ProxyServiceImpl.class); public static void main(String args[]) throws Exception{ Options ops = new OptionsBuilder().include(ProxyRunTest.class.getSimpleName()) .forks(1).build(); new Runner(ops).run(); } //方法注解,表示该方法是需要进行 benchmark 的对象。 @Benchmark public void CglibProxyRun(){ proxyServiceCglib.run(); } @Benchmark public void JdkProxyRun(){ proxyServiceJdk.run(); } @Benchmark public void JavassistProxyRun(){ proxyServiceJavassist.run(); } }

     

    测试结果

     

    第一次测试
    Benchmark Mode Cnt Score Error Units ProxyRunTest.CglibProxyRun avgt
    20 9.918 ± 1.268 ns/op ProxyRunTest.JavassistProxyRun avgt 20 34.226 ± 2.655 ns/op ProxyRunTest.JdkProxyRun avgt 20 5.225 ± 0.449 ns/op 第二次测试 Benchmark Mode Cnt Score Error Units ProxyRunTest.CglibProxyRun avgt 20 6.975 ± 0.629 ns/op ProxyRunTest.JavassistProxyRun avgt 20 31.707 ± 0.885 ns/op ProxyRunTest.JdkProxyRun avgt 20 5.442 ± 0.514 ns/op 第三次测试 Benchmark Mode Cnt Score Error Units ProxyRunTest.CglibProxyRun avgt 20 8.079 ± 1.381 ns/op ProxyRunTest.JavassistProxyRun avgt 20 33.916 ± 2.904 ns/op ProxyRunTest.JdkProxyRun avgt 20 5.947 ± 0.498 ns/op

     

    从测试结果来看,javassist的代理对象调用执行性能最差。最好的是JDK方式。

    总结

    1.不管是代理创建还是方法调用执行,Javassist方式的性能最好,JDK的方式最差。

    2.对于实际使用过程中。代理对象一般只会创建一次,创建完成后缓存起来供后续使用,因此创建过程的性能对整体性能影响不大。JDK方式和CGLIB方式的方法调用执行性能差不多,实际可根据代理对象有无接口进行选择。

     

    posted @ 2019-07-11 03:21 冬眠的山谷 阅读(...) 评论(...) 编辑 收藏
  • “两学一做”在山西——黄河新闻网 2019-07-13
  • 内地生报读香港高校本科人数持续下跌 2019-07-13
  • 【学习时刻】人民大学王义桅:金砖合作的“自信”与“自觉” 2019-07-12
  • 女子请“私家侦探”被骗3万 警方循线捣毁诈骗团伙 2019-07-11
  • 【学习时刻】北交大马院院长韩振峰:高校思想政治工作必须牢牢把握三大根本问题 2019-07-11
  • 全国“非遗”保护工作先进名单公布 2019-07-01
  • 紫光阁中共中央国家机关工作委员会 2019-06-25
  • 杭州控烟令修改草案拟允许室内设吸烟区,控烟专家:跌破眼镜 2019-06-25
  • 挪用近30万报纸征订款赌博 河南一报社聘用制干部获刑 2019-06-23
  • 2016年,有1145家上市公司大小非减持了3600亿元,还有210名上市公司高管减持了1400亿元。IPO已成了造就成千上万个十亿、百亿富豪的捷径, 2019-06-21
  • 专家“把脉”中国电影市场:提升品质方能逆袭 2019-06-21
  • “善款资助副局长儿子留学”真相须尽快落地 2019-06-19
  • 21岁女护士失联2天后确认遇害 嫌疑人为其前男友 2019-06-19
  • 中国地质公园名录旅行地中国国家地理网 2019-06-13
  • 玄关运用有四大原则 用的好才能财旺挡煞聚财 ——凤凰网房产 2019-06-10
  • 双色球16010期子墨公式定篮 幸运飞艇公式规律 079期连码三中三 农村神童送四肖中特 广西快三时时彩 壬天堂分分彩官网 广西快三和值专家推荐 三分彩是什么彩票 广东11选5手机预测软件 体彩6+1开奖查询 电子游艺机投币机 贵州11选5任三专家推荐 足彩半全场开奖 内蒙古十一选五玩法表 半全场主主是什么意思