本文翻译自: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代码时是否作弊?相关推荐

  1. java vo转map_Jython:在 Java 程序里运行 Python 代码 4.5

    彭翌 彭翌,网易游戏资深运维开发工程师,从事大数据相关的基础架构平台研发工作,业余时间也关注分布式系统等相关领域. 前言 众所周知,JVM 在大数据基础架构领域可以说是独占鳌头,当我们需要开发大数据处 ...

  2. Pycharm运行项目代码时输入可选参数

    当我们在跑神经网络的代码时,需要输入一些可选参数,比如权重文件.数据路径等一些参数时,就需要在pycharm输入参数,下面是输入参数的方法: 1.点击pycharm右上角的这个按钮,选中"E ...

  3. java -jar命令运行jar包时指定外部依赖jar包

    大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个jar包的程序入口.具体的方法是修改jar包内目录META-INF下的MANIFE ...

  4. linux环境下运行open error,错误:运行OpenCL代码时clGetPlatformIDs -1001(Linux)

    (Mods:我不确定这篇文章是否应该转移到AskUbuntu,因为这是一个与Linux bumblebee相关的问题,而不是OpenCL本身?) 好的,所以我设法在经过大量的努力后解决了这个问题. 我 ...

  5. 怎么找不到JAVA9_在Java 9上运行应用程序时获取错误“找不到模块”:log4j.core

    [INFO] ---------------------------------------------- --------------- [ERROR] /C:/Users/sumit.garg/w ...

  6. python跑代码电脑卡住_在连续运行python代码时,最终导致我的计算机崩溃

    看起来,当我运行我的代码最初几次运行它运行得很好,但在大约第3次到第4次我运行它开始放慢速度.那是我的电脑变得没有反应,因为它似乎发展了一些滞后.最终,这会使我的计算机崩溃,使在空闲状态下编码变得困难 ...

  7. python编写代码时零_python – KeyError:运行打包代码时为0L

    我有一个名为rra.py的脚本,它具有以下skelton结构: usn="" usnl=[] from bs4 import BeautifulSoup import re imp ...

  8. linux运行程序开启了opencl,错误:运行OpenCL代码时,clGetPlatformIDs -1001(Linux)

    (Mods:我不确定这个帖子是否应该转移到AskUbuntu,因为这是一个与Linux bumblebee相关的问题,而不是OpenCL本身?) 好吧,所以我设法解决这个问题后,大量的努力. 有两件事 ...

  9. java -jar vm参数_java相关:运行jar程序时添加vm参数的方法

    java相关:运行jar程序时添加vm参数的方法 发布于 2020-3-15| 复制链接 下面小妖就为大家带来一篇运行jar程序时添加vm参数的方法.小妖觉得挺不错的,现在就分享给大家,也给大家做个参 ...

最新文章

  1. Failure [INSTALL_FAILED_ALREADY_EXISTS
  2. Sphinx+gitee+Read the Docs搭建在线文档系统
  3. IIS 7.0 部署MVC
  4. 开源的酷炫猜歌喝酒小程序
  5. Oracle 有long类型字段的表 使用insert into select 语句 ,出现:ORA-00997 错误
  6. Luogu2261 [CQOI2007]余数求和
  7. QT信号(signal)和槽(slot)问题
  8. 解决Macbook网络连接成功但是图标一直显示正在查找网络问题
  9. c# 保存数据到txt (追加)
  10. 关于VLAN划分的项目案例
  11. 电子文档秒变手写文字:这个工具绝了!!
  12. cmd安装pip以及第三方库的最简单的安装方法
  13. //css 层叠样式表(Cascading Style Sheets)
  14. 十年一剑,股票自动交易实验(寻找股海宝藏之旅—解锁股市交易更多姿势)
  15. 安卓蓝牙实现即时通讯功能
  16. CLOSE关闭连接的各种情况
  17. C语言第二课,分支语句和循环语句
  18. python机器识别追踪_多目标追踪器:用OpenCV实现多目标追踪(C++/Python)
  19. 一个免费开源、跨平台的可视化源码探索项目
  20. macOS系统安装NMAP扫描工具

热门文章

  1. Android中AIDL的使用详解
  2. Spring 定时任务之 @Scheduled cron表达式
  3. Binder通信模型 :ServiceManager
  4. 看图说话:OpenGL模型矩阵和投影矩阵
  5. 【Android】Service几个重要的方法运行在哪个线程
  6. Android 蓝牙启动流程(以及设置蓝牙为作为sink模式 接收端模式)
  7. 第四周项目三-随机数函数应用于游戏(猜数字游戏)
  8. API 23之前的版本都是自动获取权限,而从 Android 6.0 开始添加了权限申请的需求,更加安全。
  9. View及ViewGroup的事件分发及传递(二)
  10. 关于设置GridControl属性在代码中的顺序带来的不同效果