我正在对一些代码进行基准测试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
即使使用完全相同的代码,使用BigInteger的JDK版本也要比使用我的版本快三倍。
我已经用javap检查了字节码,并在使用options运行时比较了编译器的输出:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
并且两个版本似乎生成相同的代码。那么,热点是否使用了一些我无法在代码中使用的预先计算的优化呢?我一直都知道他们没有。是什么解释了这种差异?
是的,HotSpot
JVM有点“作弊”,因为它具有某些BigInteger
方法的特殊版本,您无法在Java代码中找到这些方法。这些方法称为JVM内部函数。
特别BigInteger.multiplyToLen
是HotSpot中的一种内部方法。JVM源库中有一个特殊的手工编码程序集实现,但仅适用于x86-64体系结构。
您可以禁用此instrinsic
-XX:-UseMultiplyToLenIntrinsic
选项,以强制JVM使用纯Java实现。在这种情况下,性能将类似于复制代码的性能。
PS
这是其他HotSpot内部方法的列表。
我正在对一些代码进行基准测试,但我无法使它像使用那样快速运行,即使在使用完全相同的算法时也是如此。因此,我将源代码复制到自己的包中,并尝试了以下操作: 当我运行这个(在MacOS上运行jdk 1.8.0_144-B01)时,它会输出: 当我在未注释导入行的情况下运行它时: 使用JDK版本的BigInteger比我的版本快三倍,即使它使用的代码完全相同。 我已经用javap检查了字节码,并比较了使用
问题内容: 我有一个安排计时器的游戏。我有这个CoresManager文件: 我在游戏中使用这个: 如果播放器注销并且服务器重新启动,CoresManager计时器将停止运行。为了使其再次运行,我添加了代码以使其在您再次登录后再次执行startTimer()。但是,由于如果服务器未注销,计时器仍在运行,因此计时器开始运行两次。根据您注销和登录的次数,计时器开始减去2或更多。我认为,如果有代码确定计
问题内容: 可以在本地运行JAR文件。下一步是在另一台PC上运行它。 问题是运行JAR文件是否需要JRE,JDK或两者都需要? 问题答案: JDK包含JRE。 大多数程序仅需要JRE(Java运行时环境),但是某些程序在运行时需要编译器,在这种情况下,您需要JDK。 如果您拥有JDK,则也不需要JRE。
问题内容: 使用JDK 1.6进行编译时,是否可以选择构建可在JRE 1.5上运行的Java代码? PS:我是Java新手。 问题答案: 如果使用1.6编译代码,则它将无法在1.5上运行。如果您希望它在1.5中运行,则可以使用1.5编译代码,并且它可以在两者上运行。 尝试使用1.5进行编译,如果有错误,则将其发布。无法在1.5上编译的唯一方法是,如果在代码中使用特定的1.6增强功能。 回答真正的问
问题内容: 现在我有了一些C源代码,我想在我的Java应用程序中使用它。我需要执行C源代码,并将结果返回到我的Java应用程序。与其将所有C源代码重写为Java,我如何在Java应用程序中重用C源代码? 问题答案: 看一下Java Native Interface 。 Java本机接口(JNI)是一种编程框架,它使Java虚拟机(JVM)中运行的Java代码能够被本机应用程序(特定于硬件和操作系统
问题内容: 如何检测代码是否在Eclipse IDE中运行 问题答案: 我不知道获取此类信息的通用方法。 一个建议: 当您在Tomcat中启动Java程序(或Web服务器)时,只需添加一个参数即可表明该程序是由Eclipse启动的。 您可以通过打开“打开运行对话框”(“运行”菜单),然后选择您的应用程序类型并在“参数”选项卡中添加a来实现。 在您的Java代码中,您可以检查属性的值: 这样,如果程