我正在对一些代码进行基准测试,但我无法使它像使用java.math.biginteger
那样快速运行,即使在使用完全相同的算法时也是如此。因此,我将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);
}
}
当我运行这个(在MacOS上运行jdk 1.8.0_144-B01)时,它会输出:
12089nsec/mul
2559044166
当我在未注释导入行的情况下运行它时:
4098nsec/mul
2559044166
使用JDK版本的BigInteger比我的版本快三倍,即使它使用的代码完全相同。
我已经用javap检查了字节码,并比较了使用选项运行时的编译器输出:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
而且这两个版本似乎生成了相同的代码。那么hotspot是否使用了一些我不能在代码中使用的预先计算的优化呢?我一直明白他们不是。如何解释这种差异?
在Java书8中,这的确是一个内在的方法;对该方法稍作修改的版本:
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;
}
运行此文件时使用:
java -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining
-XX:+PrintIntrinsics
-XX:CICompilerCount=2
-XX:+PrintCompilation
<YourClassName>
这将打印很多行,其中一个行是:
java.math.BigInteger::multiplyToLen (216 bytes) (intrinsic)
另一方面,在Java 9中,这个方法似乎不再是一个内在的,但反过来,它调用了一个内在的方法:
@HotSpotIntrinsicCandidate
private static int[] implMultiplyToLen
所以在Java 9下运行相同的代码(使用相同的参数)会发现:
java.math.BigInteger::implMultiplyToLen (216 bytes) (intrinsic)
下面是方法的相同代码--只是略有不同的命名。
是的,HotSpot JVM有点“作弊”,因为它有一些biginteger
方法的特殊版本,而这些方法在Java代码中是找不到的。这些方法被称为JVM内含。
特别是biginteger.multipytolen
是Hotspot中的固有方法。在JVM源库中有一个特殊的手工编码汇编实现,但仅针对x86-64体系结构。
您可以使用-xx:-useMultiplyTolenintrinsic
选项禁用此instrinsic来强制JVM使用纯Java实现。在这种情况下,性能将与复制代码的性能相似。
附注。下面是其他HotSpot内部方法的列表。
问题内容: 我正在对一些代码进行基准测试,即使使用完全相同的算法,也无法使其运行速度与一样快。因此,我将源代码复制到自己的程序包中并尝试了以下操作: 当我运行此命令(在MacOS上为jdk 1.8.0_144-b01)时,它输出: 当我在未注释导入行的情况下运行它时: 即使使用完全相同的代码,使用BigInteger的JDK版本也要比使用我的版本快三倍。 我已经用javap检查了字节码,并在使用o
问题内容: 大约一年前,我偶然发现了Java的一个不错的功能,我一生都找不到。 通过一些魔术接口,显然可以在运行时声明一些可替换的类或函数。 我找到了一个很好的示例指南,该人运行了一个简单的小程序,该程序打印了一条特定的消息,然后他使用一种我不记得的方法更新了该程序,然后突然该程序将旧的打印功能替换为新的打印功能。 我尝试浏览Java API来激发我的记忆力和谷歌搜索功能,但没有成功。有人可以帮忙
问题内容: codepad.org允许您在线运行C,C ++,D等代码,但不能运行Java …我可以使用Java的网站吗? 问题答案: 还有http://ideone.com/(支持多种语言)
这是我第一次使用OkHttp,我想先研究一些基本的代码。 这是代码,从这里开始: 在Eclipse上运行代码会产生以下输出: 线程“main”java中出现异常。lang.NoClassDefFoundError:okhttp3处的kotlin/TypeCastException。回应书。在okhttp3上创建(ResponseBody.java:210)。内部的Util。(Util.java:6
我收到一个HTTP错误:运行sturts 2应用程序时出现503服务不可用错误。确切的误差是 HTTP错误:503访问/project\u 47/WEB-INF/classes/action/action\u-trial时出现问题。Java语言原因: 由Jetty提供支持:// 我的控制台如下所示: 在端口8080上启动预览服务器 模块:project_47(/project_47)