禁用JIT和执行时间

时间:2013-11-18 18:41:50

标签: java bash statistics

我正在尝试对JVM中JIT编译器的性能进行(非常,非常,简化)统计研究,以获取统计类项目。为此,我做了一个简单的算法,使用通用算法(mergesort)对随机向量进行排序,并以纳秒为单位输出执行时间(使用system.nanoTime(),可能拼写错误),以及在使用之间交替的bash脚本jit而不是使用它。我第一次运行它时获得了相当可观的结果,使用jit执行的速度大约快了3倍,但我之前运行了多次,结果(使用相同的jar文件和脚本)完全不同。令人惊讶的是,在下面的脚本运行中,使用JIT的时间略高,这意味着程序在JIT中运行速度较慢,但​​不是很明显。

如果我没有得到第一个结果,我不会对我得到的结果感到惊讶,因为如此短的程序可能JIT甚至没有时间做一些优化,并且相反增加了成本的一点开销,但是增加矢量的大小或者要排序的矢量数(对于像10000或20000这样的数字)并没有改变任何东西。

我开始认为我没有正确地禁用jit,我不得不说我不止一次得到了预期的(更快的JIT)结果,但我在执行程序时主要得到其他值。我正在使用的脚本非常简单:

#!/bin/bash

COUNTER=0

#Clear the output files
echo "TIME WITH JIT" > file_jit.out
echo "TIME WITHOUT JIT" > file_nojit.out

#Generate data
while [  $COUNTER -lt $1 ]; do
    echo "$COUNTER of $1 run data."
    #----------THOSE ARE THE TWO IMPORTANT LINES-----------
    java -jar SortTime.jar >> file_jit.out
    java -Xint -jar SortTime.jar >> file_nojit.out
    #------------------------------------------------------
COUNTER=$(($COUNTER+1))  
done 

如您所见,我正在使用-Xint选项强制解释模式(禁用JIT)。我也尝试过Djava.compiler = NONE,结果完全相同,所以我选择了这个,因为它更紧凑。

这是我的java版本的输出:

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

正如您可能已经看到我使用的是linux,ubuntu 13.04(64位)和我正在使用的笔记本电脑有AMD E1-1200双核处理器(1.4Ghz)和8GB RAM。

任何解决方案/解决方法都会非常感激,请注意,我不是在尝试对Java的JIT效率进行精确研究,而是尝试就如何管理与软件世界相关的统计数据进行课堂练习,所以我的研究有效性的评论是无关紧要的。

非常感谢。

2 个答案:

答案 0 :(得分:2)

使用-Xint运行程序可确保不编译任何方法。但是,在默认模式下运行并不能保证您的any函数(例如mergesort)将被JIT控制。

  

我正在尝试对(非常,非常,简化的)统计学进行研究   JIT编译器的性能

这并不像听起来那么容易。 JVM不具有确定性,并且还有其他因素可能会影响您的结果,例如垃圾收集。

您可能会尝试使用-XX:+PrintCompilation运行以查看您的方法是否正在进行JIT。 Hotspot只会编译重复调用的方法。

答案 1 :(得分:1)

即使启用了JIT,JVM也不会始终执行JIT。 JIT(=在运行时将Java字节代码编译为本机代码)具有不可忽略的成本,因此JVM仅在期望编译开销可以通过本机代码的性能增益抵消时才执行JIT。简单地说,JVM在期望目标Java字节代码将重复执行多次时执行JIT。

因此,如果要比较JIT和解释器之间的性能,则必须确保执行JIT编译。我的建议是:在开始测量性能之前做很多循环以确保执行JIT。

// Virtual code.

// Urge the JVM to perform JIT for doSomething.
for (int i = 0; i < 1000000; ++i) {
    doSomething();
}

// Then, measure the performance.
long startTimestamp = System.currentTimeMillis();
for (int i = 0; i < 1000000; ++i) {
    doSomething();
}
long endTImestamp = System.currentTimeMillis();