• Java中"或"运算与"与"运算快慢的三三两两


    先上结论

    模运算运算慢20%到30%

    这是通过实验的方式得到的结论.因为没有大大可以进行明确指导,所以我以最终运行的结果为准.欢迎指正.

    测试代码

    @Test
    public void test10() {
        int a, b, temp, count = 100000000;
        long start, time;
    
        Random random = new Random();
    
    
        while (true) {
            System.out.println("-----------------------------------------------");
            a = random.nextInt();
            b = random.nextInt();
    
            // 模运算部分
            start = System.currentTimeMillis();
            for (int i = 0; i < count; i++) {
                temp = a % b;
                preventOptimization(temp);
            }
            long modulo = System.currentTimeMillis() - start;
    
            // 与运算部分
            start = System.currentTimeMillis();
            for (int i = 0; i < count; i++) {
                temp = a & b;
                preventOptimization(temp);
            }
            long and = System.currentTimeMillis() - start;
    
            // 计算两种运算的比
            BigDecimal bigDecimal = new BigDecimal(and)
                    .divide(new BigDecimal(modulo), 6, ROUND_DOWN);
            System.out.println(String.format("modulo: %sms, and: %sms, scale: %s", modulo, and, bigDecimal));
        }
    }
    
    //    private static int preventOptimizationVar = 0; // A
    
    /**
     * 用于阻止jvm的字节码优化技术生效,优化掉for循环中的代码<br>
     *
     * @param num
     */
    private static void preventOptimization(int num) {
    //        preventOptimizationVar += num; // A
    }
    

    注意事项

    启动时,需要添加JVM参数-Djava.compiler=NONE阻止虚拟机的JIT优化

    一些迷之调用的解释

    1. 方法preventOptimization的作用本来是为了防止for循环内的运算单元被优化.从结果看,无法抵御JIT优化,实际上只阻止了字节码优化.
    2. 同样是方法preventOptimization.内部添加了一个对成员变量preventOptimizationVar的操作,本意同样是是为了阻止JIT优化,但效果出现偏差.
    3. 最终,只能使用JVM参数-Djava.compiler=NONE阻止JIT优化,同时调用空方法preventOptimization阻止字节码优化
    4. 为了整理其中的关联,进行如下整理

    针对preventOptimization方法,preventOptimizationVar操作与-Djava.compiler=NONE参数之间的交叉测试

    --------------------------- -Djava.compiler=NONE 不使用-Djava.compiler=NONE
    preventOptimization(空方法) 目标结果 只能执行第一次while,之后除数为0抛出异常.应该是for循环被优化掉了
    preventOptimization 执行变得极慢且比值随机位于1两侧.可能是因为操作成员变量的时间已经把运算的时间稀释了 两种运算的for的平均用时只有个位数的毫秒数.一般为4ms或5ms.可以断定发生了JIT优化.但是这又与完全跳过for循环的行为不同.中间产生了数毫秒的操作时间.
    不调用preventOptimization 目标结果 只能执行第一次while,之后除数为0抛出异常.应该是for循环被优化掉了

    注: 上面的测试结果基于intel平台上的ubuntu18.4操作系统.后面我会补上AMD平台上的Windows系统的执行表格.它们之间会有轻微的不同

    后记

    1. 针对-Djava.compiler=NONE,明确的禁用了JIT优化
    2. 针对字节码优化需要回去翻书确认实际作用与效果
    3. 这个代码在不同的物理机上出现了一些差异.家中的电脑是AMD的锐龙CPU,其结果恒定为0.73左右.而在公司的Intel CPU上运行,结果稳定在0.87左右.
    4. 目前我无法这种计算方式是否是正确的,虽然得出了模运算运算慢的结论.身边没有大大,无法对我的这种做法进行评价.也就无法确定结果的正确性.也就是说,我有可能用了错误的方式,得到这正确的答案.这种可能的本末倒置实在让人头痛.

    后记的后记

    对于目前的这种情况.要想完全弄清谁快谁慢,其实可以用一个最简单也最直观的方法进行确认.那就是去翻JDK源码.先在字节码里找到负责运算与运算的指令,然后去找这个指令JDK实现

    更新

    看了下编译后的字节码,代码中使用了如下的指令进行操作

    1. 运算使用指令irem.将操作数栈的两个值进行余运算(注意,这里用的是余运算.它不同于模运算)
    2. 运算使用指令iand.将操作数栈的两个值进行与运算

    下面需要找到JDK是怎么执行字节码文件中的每个指令的.

    不要和我说什么几个阶段,每个阶段都干什么.这可能是个大坑.所以我得翻书(鸽了)啊

  • 相关阅读:
    RTSP/GB28181/HIKSDK/Ehome协议视频平台EasyCVR预览流添加自定义信息方法介绍
    RTSP/GB28181/HIKSDK/Ehome协议视频上云服务平台EasyCVR人脸识别开发ArcSoftFace环境搭建
    如何在同一系统的电脑中同时启动2个不同版本的RTSP协议网页无插件直播视频平台EasyNVR?
    RTSP网络摄像头网页无插件直播视频平台EasyNVR自定义标题和CopyRight步骤
    H265网页视频播放器播放录像时间轴与实际视频时间不相符如何处理?
    【方案搭建】搭建智慧工厂实时视频监控系统有哪些方式?国标平台EasyGBS及EasyCVR平台对比
    如何在RTSP协议网页无插件直播流媒体视频平台EasyNVR演示系统内做到自定义断流?
    【解决方案】RTSP协议网页无插件直播视频平台EasyNVR如何通过CDN连通内外网实现连锁餐饮企业远程监控管理系统?
    RTSP协议网络摄像头网页无插件直播流媒体服务器平台EasyNVR显示视频不在线如何排查?
    数据库应用系统功能设计与实施
  • 原文地址:https://www.cnblogs.com/heaven-elegy/p/11896889.html
Copyright © 2020-2023  润新知