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

先上结论

模运算运算慢20%到30%

这是经过实验的方式获得的结论.由于没有大大能够进行明确指导,因此我以最终运行的结果为准.欢迎指正.java

测试代码

@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优化ubuntu

一些迷之调用的解释

  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系统的执行表格.它们之间会有轻微的不一样dom

后记

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

后记的后记

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

更新

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

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

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

不要和我说什么几个阶段,每一个阶段都干什么.这多是个大坑.因此我得翻书(鸽了)啊ide

相关文章
相关标签/搜索