这是经过实验的方式获得的结论.由于没有大大能够进行明确指导,因此我以最终运行的结果为准.欢迎指正.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
preventOptimization
的做用原本是为了防止for循环内的运算单元被优化.从结果看,没法抵御JIT优化,实际上只阻止了字节码优化.preventOptimization
.内部添加了一个对成员变量preventOptimizationVar
的操做,本意一样是是为了阻止JIT优化,但效果出现误差.-Djava.compiler=NONE
阻止JIT优化,同时调用空方法preventOptimization
阻止字节码优化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
-Djava.compiler=NONE
,明确的禁用了JIT优化对于目前的这种状况.要想彻底弄清谁快谁慢,其实能够用一个最简单也最直观的方法进行确认.那就是去翻JDK源码.先在字节码里找到负责与运算与模运算的指令,而后去找这个指令的JDK实现jvm
irem
.将操做数栈的两个值进行余运算(注意,这里用的是余运算.它不一样于模运算)iand
.将操做数栈的两个值进行与运算不要和我说什么几个阶段,每一个阶段都干什么.这多是个大坑.因此我得翻书(鸽了)啊ide