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优化
一些迷之调用的解释
- 方法
preventOptimization的作用本来是为了防止for循环内的运算单元被优化.从结果看,无法抵御JIT优化,实际上只阻止了字节码优化. - 同样是方法
preventOptimization.内部添加了一个对成员变量preventOptimizationVar的操作,本意同样是是为了阻止JIT优化,但效果出现偏差. - 最终,只能使用JVM参数
-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系统的执行表格.它们之间会有轻微的不同
后记
- 针对
-Djava.compiler=NONE,明确的禁用了JIT优化 - 针对字节码优化需要回去翻书确认实际作用与效果
- 这个代码在不同的物理机上出现了一些差异.家中的电脑是AMD的锐龙CPU,其结果恒定为0.73左右.而在公司的Intel CPU上运行,结果稳定在0.87左右.
- 目前我无法这种计算方式是否是正确的,虽然得出了模运算比与运算慢的结论.身边没有大大,无法对我的这种做法进行评价.也就无法确定结果的正确性.也就是说,我有可能用了错误的方式,得到这正确的答案.这种可能的本末倒置实在让人头痛.
后记的后记
对于目前的这种情况.要想完全弄清谁快谁慢,其实可以用一个最简单也最直观的方法进行确认.那就是去翻JDK源码.先在字节码里找到负责与运算与模运算的指令,然后去找这个指令的JDK实现
更新
看了下编译后的字节码,代码中使用了如下的指令进行操作
- 模运算使用指令
irem.将操作数栈的两个值进行余运算(注意,这里用的是余运算.它不同于模运算) - 与运算使用指令
iand.将操作数栈的两个值进行与运算
下面需要找到JDK是怎么执行字节码文件中的每个指令的.
不要和我说什么几个阶段,每个阶段都干什么.这可能是个大坑.所以我得翻书(鸽了)啊
Java中"或"运算与"与"运算快慢的三三两两的更多相关文章
- Java中Byte类型数据在运算中的问题
比如: byte a=1; byte b=2; byte c; c=a+b; //这样是计算不出c,是错误的 c=a+1; //这样也是不能计算c的 c=64+1; //为什么这样就能计算c,在Jav ...
- 关于JAVA中Byte数据类型二进制赋值运算报错问题
自从JDK7更新之后,新增了二进制变量的表示,支持将整数类型用二进制来表示,用0b开头: 例如: byte b= (byte) 0b1000_0001; short s = (short) 0b100 ...
- java中&和&&的区别 位运算
1.1. 逻辑与的运算符功能 1.1.1. 测试&& public static void main(String[] args) { int x=5; if (x==6 && ...
- Java中使用md5进行hash运算
public class Md5Util { /** * @author Bean_bag * @description 进行Hash运算 * * @param input 参数字符串 * @retu ...
- 042、Java中逻辑运算之短路或运算“||”
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- 041、Java中逻辑运算之普通或运算“|”
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- 040、Java中逻辑运算之短路与运算“&&”
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- 039、Java中逻辑运算之普通与运算“&”
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- Java中「与运算,或运算,异或运算,取反运算。」
版权声明一:本文为博主原创文章,转载请附上原文出处链接和本声明.版权声明二:本网站的所有作品会及时更新,欢迎大家阅读后发表评论,以利作品的完善.版权声明三:对不遵守本声明或其他违法.恶意使用本网内容者 ...
- java使用DateUtils对日期进行运算
最近在写数据上传的程序,需要对Date进行一些数学运算,个人感觉在java中,日期的数学运算还是比较常用的,所以把Date的数学运算都玩了一下.试了一下,发现DateUtils这个工具类对于Date的 ...
随机推荐
- Java基础面试相关
面试相关的问题(下) 四 Linux高级_ 1.Linux机器 变慢,怎么查看? (1)整机的性能 主要查看的是CPU和内存 先查看整机的top,使用命令 top 虚拟机 使用1可以查看哪个核被占用过 ...
- springboot读取resource下的文件
public static String DEFAULT_CFGFILE = ConfigManager.class.getClassLoader().getResource("conf/s ...
- react文本溢出hover气泡显示全部文本——JS判断文本溢出
需求: 在文本溢出的时候,显示气泡 JS相关知识 // target js元素 const containerLength = target.width; //当前容器的宽度 const textLe ...
- openstack网络(二)
连接物理服务器 单网卡 多网卡 跨主机安装网络服务 使用单个控制节点安装 使用专用网络节点安装 连接物理服务器 每个物理主机所需的网卡数量取决于云平台使用领域,组织的安全性和性能要求以及硬件的可用性. ...
- Spring源码学习笔记之基于ClassPathXmlApplicationContext进行bean标签解析
bean 标签在spring的配置文件中, 是非常重要的一个标签, 即便现在boot项目比较流行, 但是还是有必要理解bean标签的解析流程,有助于我们进行 基于注解配置, 也知道各个标签的作用,以及 ...
- 十大C++实战项目,你会几个?【高薪必备】
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:实验楼 市面上有很多C++的实战项目,从简单到进阶,学习每个项目都 ...
- .net core 微服务通讯组件Orleans的使用与配置
Orleans非常好用 并且支持.net core 社区也非常活跃 Orleans2.0+在国内的教程偏少 多数是1.5版本的教程 在这里写上四篇Orleans教程 目录 1.Orleans的入门教程 ...
- 攻略前端面试官(三):JS的原型和原型链
本文在个人主页同步更新~ 背就完事了 介绍:一些知识点相关的面试题和答案 使用姿势:看答案前先尝试回答,看完后把答案收起来检验成果~ 面试官:什么是构造函数 答:构造函数的本质是一个普通函数,他的特点 ...
- 基于iSensor的MT9M001C12STM传感器调试总结
iSensor APP 之 摄像头调试 MT9M001C12STM iSensor app 非常适合调试各种摄像头,已测试通过的sensor有: l OV7670.OV7725.OV9650.OV ...
- springboot搭建一个简单的websocket的实时推送应用
说一下实用springboot搭建一个简单的websocket 的实时推送应用 websocket是什么 WebSocket是一种在单个TCP连接上进行全双工通信的协议 我们以前用的http协议只能单 ...