您的位置:首页 > 编程语言 > Java开发

好记性不如烂笔头48-java拦截器-JDK自带动态代理和CGLIB效率比较(3)

2015-02-11 10:04 609 查看
Java中自带的动态代理的类必须要实现一个接口,而且据说使用反射的效率也并不是很高。于是CGLIB就诞生了。

使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,理论上比使用Java反射效率要高。

那么我们测试下,这个运行的效率如何。

1、 测试的准备情况

准备1:好记性不如烂笔头46-java拦截器-彻底理解动态代理的概念(1) /article/2390007.html

准备2: 好记性不如烂笔头47-java拦截器-用CGLib实现动态代理(2)

/article/2390008.html

为了测试结果方便观察,把所有的打印输出关闭。

JDK版本: jdk1.6.0_25

2、 测试运行效率的源代码

[code]package com.tools;

import com.CGLib.WangBaoQiang;
import com.proxy.Actor;
/**
 * 使用预热模式
 * JVM参数:-XX:PrintCompilation
 * @author 范芳铭
 */
public class BaseRun_Proxy_Test {
    public static void main(String[] args) throws Exception{
        int warmUpCycles = 1000000; //预热次数
        BaseRun_Proxy_Test se = new BaseRun_Proxy_Test();
        System.out.println("预热循环开始 ...");
        se.runTest(warmUpCycles);
        System.out.println("预热结束");

        Thread.sleep(1000); //让系统暂停

        System.out.println("进入正式循环 ...");
        se.runTest(1);
        se.runTest(100);
        se.runTest(10000);
        se.runTest(1000000);
        se.runTest(20000000); //2000千万次,我们系统一天的访问量
        System.out.println("正式运算完成");
    }

    private void runTest(int iterations){
        BaseRun_Proxy_Test lot = new BaseRun_Proxy_Test();
        //运行J***A自带动态代理
        long startTime = System.nanoTime();
        for(int i = 0 ; i < iterations ;  i ++){
            lot.getJavaProxyLoop();
        }
        long elapsedTime = System.nanoTime();
        System.out.println("运行J***A自带动态代理:" + iterations + ",结束,耗时:" + (elapsedTime-startTime));
        //运行CGLIB
        long cglibStartTime = System.nanoTime();
        for(int i = 0 ; i < iterations ;  i ++){
            lot.getCGLibLoop();
        }
        long cglibElapsedTime = System.nanoTime();
        System.out.println("运行CGLIB动态代理:" + iterations + ",结束,耗时:" + (cglibElapsedTime-cglibStartTime));
    }

    public void getJavaProxyLoop(){
        // 首先找到经纪人
        com.proxy.ActorJingJiRen proxy = new com.proxy.ActorJingJiRen();
        // 通过经纪人获得相关演员(代理对象)
        Actor p = proxy.getProxy();
        String retValue = p.sing("天下无贼");
        String value = p.dance("凤凰传奇");
    }

    public void getCGLibLoop(){
        com.CGLib.ActorJingJiRen proxy = new com.CGLib.ActorJingJiRen();
        // 通过经纪人获得相关演员(代理对象)
        WangBaoQiang p = proxy.getProxy();
        String retValue = p.sing("天下无贼");
        String value = p.dance("凤凰传奇");
    }
}


3、 运行结果

预热循环开始 …

运行J***A自带动态代理:1000000,结束,耗时:2390557348

运行CGLIB动态代理:1000000,结束,耗时:6111703990

预热结束

进入正式循环 …

运行J***A自带动态代理:1,结束,耗时:35715

运行CGLIB动态代理:1,结束,耗时:39409

运行J***A自带动态代理:100,结束,耗时:381782

运行CGLIB动态代理:100,结束,耗时:1162997

运行J***A自带动态代理:10000,结束,耗时:23943050

运行CGLIB动态代理:10000,结束,耗时:58153974

运行J***A自带动态代理:1000000,结束,耗时:2403822826

运行CGLIB动态代理:1000000,结束,耗时:5804202226

运行J***A自带动态代理:20000000,结束,耗时:48913882774

运行CGLIB动态代理:20000000,结束,耗时:118967606438

正式运算完成

4、 运行效率的表格



CGlib的动态代理的效率,看起来比J***A自带的效率要低。这个和我们所听到的情况可能不一样。

5、 其他

将CGLIB放在java自带proxy的方法之前,数据情况和上面基本一致。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: