我有一个Java程序(使用JDK 7u80编译),它大量使用了“JavaScript”ScriptEngine(JSR-223)。我注意到,与Java 7运行时环境(JRE 7u80)相比,我的程序在Java 8运行时环境(JRE 8u65)下执行时运行速度非常慢。Java 8 ScriptEngine与Java 7相比的主要性能问题
我已经把下面的SSCCE来说明问题,然后执行它的Java 7和Java 8在相同的Windows PC上:
import javax.script.*;
public class SSCCE {
public SSCCE() {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine js = sem.getEngineByName("JavaScript");
long t = 0;
int i = 0;
String gJs = "function ip2long(ip) {";
gJs += "var aIP = ip.split(\".\");";
gJs += "return (aIP[0] * Math.pow(256, 3)) + (aIP[1] * Math.pow(256, 2)) + (aIP[2] * 256) + (aIP[3] * 1);";
gJs += "}";
gJs += "function long2ip(l) {";
gJs += "if (!isNaN(l) && ((l >= 0) || (l <= Math.pow(2, 32)))) {";
gJs += "return Math.floor(l/Math.pow(256, 3)) + \".\" +";
gJs += "Math.floor((l % Math.pow(256, 3))/Math.pow(256, 2)) + \".\" +";
gJs += "Math.floor(((l % Math.pow(256, 3)) % Math.pow(256, 2))/Math.pow(256, 1)) + \".\" +";
gJs += "Math.floor((((l % Math.pow(256, 3)) % Math.pow(256, 2)) % Math.pow(256, 1))/Math.pow(256, 0));";
gJs += "}";
gJs += "return null;";
gJs += "}";
try {
js.eval(gJs);
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("Warming Up...");
t = System.nanoTime();
for (i = 0; i < 4097; i++) {
try {
String sJs = "var ip = \"192.0.2.0\";";
sJs += "var nip = long2ip(ip2long(ip, " + i + "));";
js.eval(sJs);
}
catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Starting...");
t = System.nanoTime();
for (i = 0; i < 4097; i++) {
try {
String sJs = "var ip = \"192.0.2.0\";";
sJs += "var nip = long2ip(ip2long(ip, " + i + "));";
js.eval(sJs);
}
catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Elapsed Time: " + (System.nanoTime() - t)/1000000000.0f);
}
public static void main(String[] args) {
new SSCCE();
}
}
中的JavaScript由一个IP地址转换为功能一个长,添加一个数字,然后将其转换回IP地址 - 这是重复4096次。
我看到的Java 7和Java 8的结果如下:
D:\Scripts>java7 SSCCE
Warming Up...
Starting...
Elapsed Time: 0.5856594
D:\Scripts>java8 SSCCE
Warming Up...
Starting...
Elapsed Time: 4.6862915
我应该提出这个作为与Java 8相关的性能缺陷?
UPDATED:包含预热阶段以确保所有代码路径在我的定时循环之前已经初始化。
我无法重现您的结果,可能是因为您没有包含热身阶段。 – Tunaki
这是如何重复一个没有提到Java 7和Java 8之间性能差异的问题?这是一篇提到如何做微基准的文章。如果我正确地阅读这篇文章,我应该做两次循环,但只在第二次计时? – chrixm
我建议你看看JMH做正确的基准。这是一个库,它会自动包含一个预热阶段并避免测量错误的东西。你得到的差异可能只是因为Nahsorn比Rhino需要更长的时间才能加载。 – Tunaki