为什么在树莓派上使用Open JDK和Oracle JDK之间会有如此大的性能差异?

18

在我的树莓派上,我进行了一些性能测试,如CaffeineMark和SciMark,使用两种不同的JVM。尽管我听说它们之间的差异很小,但它们之间存在着巨大的性能差异。我还尝试了使用浮点数进行计算,尽管两者都应支持硬浮点ABI,但Oracle JDK得分更高。

我使用的操作系统是Linux raspberrypi 3.18.11-v7+

OpenJDK:    
java version "1.7.0_79"  
OpenJDK Runtime Environment (IcedTea 2.5.5) (7u79-2.5.5-1~deb7u1+rpi1)  
OpenJDK Zero VM (build 24.79-b02, mixed mode)  

OracleJDK:  
java version "1.7.0_40"  
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)  
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)  

SciMark results:

                 OpenJDK            OracleJDK
Composite Score 14.280735577363213  || 32.24948180361924   
FFT (1024)      9.482866845055302   || 26.447121360843663  
SOR (100x100)   27.14938943220646   || 59.68022533004399  
Monte Carlo     3.6298604956147384  || 10.561671865446971  
Sparse matmult  15.603809523809524  || 26.64931580928407  
LU (100x100)    15.53775159013005   || 37.90907465247749 

我使用了一个以0.1步长计算到600000的程序,试图测试JVM处理浮点数的性能。

OpenJDK: 257ms
OracleJDK: 151ms

以0.1步长计算到1200000:

OpenJDK: 457ms
OracleJDK: 263ms

public class Testing {

    /**
     * @param args
     */
    public static long Test()
    {
        float counter=0.0f;
        long startTime = System.currentTimeMillis();
        while (counter <= 1_200_000.0f)
        {
            counter += 0.1f;
        }
        return System.currentTimeMillis() - startTime;
    }

    public static void main(String[] args){
        System.out.println(Test());
    }

}

我尝试了 SlipperySeal 提到的改进,并将测试放在循环中。我还尝试使用 c2 编译器,但结果并没有不同。


1
请量化。发布一些测量的性能数据。 - Stephen C
另外,请注明您使用的jdk版本 - Amey Jadiye
1
这篇文章几年前就发布了,但看起来Oracle刚刚推出了更好的JIT。另外,你可能想把整个测试放在一个循环中,因为JIT不总是立即启动。它们可以在解释模式下运行,直到发生一定数量的循环才成为JIT的候选对象。 - slipperyseal
我尝试将测试放入循环中,并使用c2编译器,但结果与其他结果没有区别。 - Laobiz
2个回答

18

OpenJDK Zero VM是一种仅有解释器的JVM。一方面,它更容易移植,因为它没有特定于架构的汇编代码,但另一方面,它的性能不佳,因为它没有特定于架构的汇编代码。

Oracle JDK利用平台的浮点ABI(RP1上的软浮点和RP2上的硬浮点)。我可以想象它拥有相当数量的汇编代码,特定于ARM架构,这就是为什么它得分更高的原因。

早期在OpenJDK Zero VM中引入了一个名为Shark的JIT编译器,基于LLVM。我不确定您的系统的OpenJDK是否使用了Shark,但很可能是。它提供了一种折衷方案,既没有汇编代码,又可以运行有效的本地代码。如果未启用Shark,则使用启用Shark的IcedTea构建将改善性能。如果启用了Shark,则这就是OpenJDK性能不佳的原因。


11

2018年4月更新。

我在树莓派3上使用Raspbian Stretch系统运行了Java Whetstone离线基准测试。源代码可以在这里Raspberry_Pi_Benchmarks/java/source code/whetstone-off-line/whetstc.java文件中找到。

结论是,openjdk-9-jre比openjdk-8-jre(测试版本1.8.0_162)更快,而openjdk-8-jre又比oracle-java8-jdk(测试版本1.8.0_65)更快。请注意,我在使用oracle-java8-jdk时使用的是旧内核。

Raspbian仓库中的openjdk-9-jdk:

$ java -version
openjdk version "9-Raspbian"
OpenJDK Runtime Environment (build 9-Raspbian+0-9b181-4bpo9rpt1)
OpenJDK Server VM (build 9-Raspbian+0-9b181-4bpo9rpt1, mixed mode)

$ java whetstc 
   Whetstone Benchmark Java Version, apr. 26 2018, 23:15:40

                                                     1 Pass
Test                  Result       MFLOPS     MOPS  millisecs

N1 floating point  -1,124750137    333,22             0,0576
N2 floating point  -1,131330490    293,19             0,4584
N3 if then else     1,000000000             185,95    0,5566
N4 fixed point     12,000000000             412,95    0,7628
N5 sin,cos etc.     0,499110132              22,40    3,7140
N6 floating point   0,999999821    212,70             2,5360
N7 assignments      3,000000000             105,66    1,7490
N8 exp,sqrt etc.    0,825148463              16,70    2,2280

MWIPS                              829,02            12,0624

Operating System    Linux, Arch. arm, Version 4.14.34-v7+
Java Vendor         Oracle Corporation, Version  9-Raspbian
CPU null

从 Raspbian 软件源安装的 openjdk-8-jdk:

$ java -version
openjdk version "1.8.0_162"
OpenJDK Runtime Environment (build 1.8.0_162-8u162-b12-1~deb9u1-b12)
OpenJDK Client VM (build 25.162-b12, mixed mode)

$ java whetstc
   Whetstone Benchmark Java Version, Apr 27 2018, 13:13:26

                                                     1 Pass
Test                  Result       MFLOPS     MOPS  millisecs

N1 floating point  -1.124750137    181.82             0.1056
N2 floating point  -1.131330490    175.92             0.7640
N3 if then else     1.000000000              88.61    1.1680
N4 fixed point     12.000000000             389.85    0.8080
N5 sin,cos etc.     0.499110132               9.35    8.8980
N6 floating point   0.999999821     76.27             7.0720
N7 assignments      3.000000000             275.82    0.6700
N8 exp,sqrt etc.    0.825148463               7.15    5.2060

MWIPS                              405.00            24.6916

Operating System    Linux, Arch. arm, Version 4.14.34-v7+
Java Vendor         Oracle Corporation, Version  1.8.0_162
CPU null

来自Raspbian仓库的oracle-java8-jdk:

$ java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode)`

$ java whetstc
   Whetstone Benchmark Java Version, Nov 15 2017, 11:16:37

                                                     1 Pass
Test                  Result       MFLOPS     MOPS  millisecs

N1 floating point  -1.124750137     91.52             0.2098
N2 floating point  -1.131330490     89.01             1.5100
N3 if then else     1.000000000              44.27    2.3380
N4 fixed point     12.000000000             229.76    1.3710
N5 sin,cos etc.     0.499110103               3.01   27.6400
N6 floating point   0.999999821     44.95            12.0000
N7 assignments      3.000000000             137.09    1.3480
N8 exp,sqrt etc.    0.751108646               0.58   63.9100

MWIPS                               90.64           110.3268

Operating System    Linux, Arch. arm, Version 4.9.35-v7+
Java Vendor         Oracle Corporation, Version  1.8.0_65
CPU null

1
很令人印象深刻的是,在这个基准测试中,RPi3与OpenJDK9相比,略逊于Core 2 Duo T7200(我每天使用的机器)。作为最后一行,在此机器上(来自Debian testing/buster的内核4.17.0-1-amd64),使用OpenJDK 10.0.2+13-Debian-1,我得到了MWIPS 1985,08 5,0376的结果。 - rbrito
客户端与服务器端虚拟机在这里是关键。它会改变JIT编译设置。 - jocull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接