Java JIT在运行JDK代码时是否作弊?
本文翻译自:Does Java JIT cheat when running JDK code?
I was benchmarking some code, and I could not get it to run as fast as with java.math.BigInteger
, even when using the exact same algorithm. 我正在对一些代码进行基准测试,即使使用完全相同的算法,也无法像java.math.BigInteger
那样快速运行。 So I copied java.math.BigInteger
source into my own package and tried this: 所以我将java.math.BigInteger
源复制到我自己的包中并尝试了这个:
//import java.math.BigInteger;public class MultiplyTest {public static void main(String[] args) {Random r = new Random(1);long tm = 0, count = 0,result=0;for (int i = 0; i < 400000; i++) {int s1 = 400, s2 = 400;BigInteger a = new BigInteger(s1 * 8, r), b = new BigInteger(s2 * 8, r);long tm1 = System.nanoTime();BigInteger c = a.multiply(b);if (i > 100000) {tm += System.nanoTime() - tm1;count++;}result+=c.bitLength();}System.out.println((tm / count) + "nsec/mul");System.out.println(result); }
}
When I run this (jdk 1.8.0_144-b01 on MacOS) it outputs: 当我运行它(在MacOS上为jdk 1.8.0_144-b01)时,它输出:
12089nsec/mul
2559044166
When I run it with the import line uncommented: 当我使用取消注释的导入行运行它时:
4098nsec/mul
2559044166
It's almost three times as fast when using the JDK version of BigInteger versus my version, even if it's using the exact same code . 使用BigInteger的JDK版本与我的版本相比,它几乎快三倍,即使它使用完全相同的代码 。
I've examined the bytecode with javap, and compared compiler output when running with options: 我用javap检查了字节码,并在运行选项时比较了编译器输出:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
and both versions seem to generate the same code. 并且两个版本似乎生成相同的代码。 So is hotspot using some precomputed optimisations that I can't use in my code? 使用一些我在代码中无法使用的预先计算优化的热点也是如此吗? I always understood that they don't. 我一直都明白他们没有。 What explains this difference? 是什么解释了这种差异
#1楼
参考:https://stackoom.com/question/36dwM/Java-JIT在运行JDK代码时是否作弊
#2楼
Yes, HotSpot JVM is kind of "cheating", because it has a special version of some BigInteger
methods that you won't find in Java code. 是的,HotSpot JVM有点“作弊”,因为它有一些你在Java代码中找不到的BigInteger
方法的特殊版本。 These methods are called JVM intrinsics . 这些方法称为JVM内在函数 。
In particular, BigInteger.multiplyToLen
is an instrinsic method in HotSpot. 特别是, BigInteger.multiplyToLen
是HotSpot中的一种内在方法。 There is a special hand-coded assembly implementation in JVM source base, but only for x86-64 architecture. JVM源代码库中有一个特殊的手工编码程序集实现 ,但仅适用于x86-64体系结构。
You may disable this instrinsic with -XX:-UseMultiplyToLenIntrinsic
option to force JVM to use pure Java implementation. 您可以使用-XX:-UseMultiplyToLenIntrinsic
选项禁用此-XX:-UseMultiplyToLenIntrinsic
以强制JVM使用纯Java实现。 In this case the performance will be similar to the performance of your copied code. 在这种情况下,性能将与您复制的代码的性能类似。
PS Here is a list of other HotSpot intrinsic methods. PS这是其他HotSpot内在方法的列表 。
#3楼
In Java 8 this is indeed an intrinsic method; 在Java 8中,这确实是一种内在的方法; a slightly modified version of the method: 稍微修改过的方法版本:
private static BigInteger test() {Random r = new Random(1);BigInteger c = null;for (int i = 0; i < 400000; i++) {int s1 = 400, s2 = 400;BigInteger a = new BigInteger(s1 * 8, r), b = new BigInteger(s2 * 8, r);c = a.multiply(b);}return c;
}
Running this with: 运行此:
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:+PrintIntrinsics -XX:CICompilerCount=2 -XX:+PrintCompilation <YourClassName>
This will print lots of lines and one of them will be: 这将打印许多行,其中一行将是:
java.math.BigInteger::multiplyToLen (216 bytes) (intrinsic)
In Java 9 on the other hand that method seems to not be an intrinsic anymore, but in turn it calls a method that is an intrinsic: 另一方面,在Java 9中 ,该方法似乎不再是内在的,而是反过来它调用一个内在的方法:
@HotSpotIntrinsicCandidateprivate static int[] implMultiplyToLen
So running the same code under Java 9 (with the same parameters) will reveal: 因此,在Java 9下运行相同的代码(具有相同的参数)将揭示:
java.math.BigInteger::implMultiplyToLen (216 bytes) (intrinsic)
Underneath it's the same code for the method - just a slightly different naming. 在它下面是该方法的相同代码 - 只是稍微不同的命名。
Java JIT在运行JDK代码时是否作弊?相关推荐
- java vo转map_Jython:在 Java 程序里运行 Python 代码 4.5
彭翌 彭翌,网易游戏资深运维开发工程师,从事大数据相关的基础架构平台研发工作,业余时间也关注分布式系统等相关领域. 前言 众所周知,JVM 在大数据基础架构领域可以说是独占鳌头,当我们需要开发大数据处 ...
- Pycharm运行项目代码时输入可选参数
当我们在跑神经网络的代码时,需要输入一些可选参数,比如权重文件.数据路径等一些参数时,就需要在pycharm输入参数,下面是输入参数的方法: 1.点击pycharm右上角的这个按钮,选中"E ...
- java -jar命令运行jar包时指定外部依赖jar包
大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个jar包的程序入口.具体的方法是修改jar包内目录META-INF下的MANIFE ...
- linux环境下运行open error,错误:运行OpenCL代码时clGetPlatformIDs -1001(Linux)
(Mods:我不确定这篇文章是否应该转移到AskUbuntu,因为这是一个与Linux bumblebee相关的问题,而不是OpenCL本身?) 好的,所以我设法在经过大量的努力后解决了这个问题. 我 ...
- 怎么找不到JAVA9_在Java 9上运行应用程序时获取错误“找不到模块”:log4j.core
[INFO] ---------------------------------------------- --------------- [ERROR] /C:/Users/sumit.garg/w ...
- python跑代码电脑卡住_在连续运行python代码时,最终导致我的计算机崩溃
看起来,当我运行我的代码最初几次运行它运行得很好,但在大约第3次到第4次我运行它开始放慢速度.那是我的电脑变得没有反应,因为它似乎发展了一些滞后.最终,这会使我的计算机崩溃,使在空闲状态下编码变得困难 ...
- python编写代码时零_python – KeyError:运行打包代码时为0L
我有一个名为rra.py的脚本,它具有以下skelton结构: usn="" usnl=[] from bs4 import BeautifulSoup import re imp ...
- linux运行程序开启了opencl,错误:运行OpenCL代码时,clGetPlatformIDs -1001(Linux)
(Mods:我不确定这个帖子是否应该转移到AskUbuntu,因为这是一个与Linux bumblebee相关的问题,而不是OpenCL本身?) 好吧,所以我设法解决这个问题后,大量的努力. 有两件事 ...
- java -jar vm参数_java相关:运行jar程序时添加vm参数的方法
java相关:运行jar程序时添加vm参数的方法 发布于 2020-3-15| 复制链接 下面小妖就为大家带来一篇运行jar程序时添加vm参数的方法.小妖觉得挺不错的,现在就分享给大家,也给大家做个参 ...
最新文章
- Failure [INSTALL_FAILED_ALREADY_EXISTS
- Sphinx+gitee+Read the Docs搭建在线文档系统
- IIS 7.0 部署MVC
- 开源的酷炫猜歌喝酒小程序
- Oracle 有long类型字段的表 使用insert into select 语句 ,出现:ORA-00997 错误
- Luogu2261 [CQOI2007]余数求和
- QT信号(signal)和槽(slot)问题
- 解决Macbook网络连接成功但是图标一直显示正在查找网络问题
- c# 保存数据到txt (追加)
- 关于VLAN划分的项目案例
- 电子文档秒变手写文字:这个工具绝了!!
- cmd安装pip以及第三方库的最简单的安装方法
- //css 层叠样式表(Cascading Style Sheets)
- 十年一剑,股票自动交易实验(寻找股海宝藏之旅—解锁股市交易更多姿势)
- 安卓蓝牙实现即时通讯功能
- CLOSE关闭连接的各种情况
- C语言第二课,分支语句和循环语句
- python机器识别追踪_多目标追踪器:用OpenCV实现多目标追踪(C++/Python)
- 一个免费开源、跨平台的可视化源码探索项目
- macOS系统安装NMAP扫描工具
热门文章
- Android中AIDL的使用详解
- Spring 定时任务之 @Scheduled cron表达式
- Binder通信模型 :ServiceManager
- 看图说话:OpenGL模型矩阵和投影矩阵
- 【Android】Service几个重要的方法运行在哪个线程
- Android 蓝牙启动流程(以及设置蓝牙为作为sink模式 接收端模式)
- 第四周项目三-随机数函数应用于游戏(猜数字游戏)
- API 23之前的版本都是自动获取权限,而从 Android 6.0 开始添加了权限申请的需求,更加安全。
- View及ViewGroup的事件分发及传递(二)
- 关于设置GridControl属性在代码中的顺序带来的不同效果