【问题标题】:Oracle vs IBM Java performanceOracle 与 IBM Java 性能对比
【发布时间】:2017-10-12 11:37:20
【问题描述】:

我正在尝试比较两个主要 Java 实现的性能:Oracle 和 IBM 在运行以下测试时:

public class HarmonicSeriesTest {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        final int limit = 20;
        double sum = 0.0;
        long n = 0;
        while (sum < limit) {
            n++;
            sum += 1.0 / n;
        }
        long duration = System.currentTimeMillis() - startTime;
        System.out.printf("n is %d\n", n);
        System.out.printf("Executed in %d miliseconds\n", duration);
    }
}

通过运行上面的代码:

  1. IBM JRE 1.8.0

java 版本“1.8.0”Java(TM) SE 运行时环境(构建 pwa6480sr3fp22-20161213_02(SR3 FP22)) IBM J9 VM(内部版本 2.8,JRE 1.8.0 Windows 10 amd64-64 压缩参考 20161209_329148 (JIT 启用,启用 AOT)J9VM - R28_20161209_1345_B329148 JIT - tr.r14.java.green_20161207_128946 GC - R28_20161209_1345_B329148_CMPRSS J9CL - 20161209_329148) JCL - 20161213_01 基于Oracle jdk8u111-b14

  1. Oracle JRE 1.8.0_131

java 版本 "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64 位服务器 VM(内部版本 25.131-b11,混合模式)

  1. Sun JRE 1.5.0_22

java 版本“1.5.0_22”Java(TM) 2 运行时环境,标准 版本 (build 1.5.0_22-b03) Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_22-b03,混合模式)

我一直得到以下结果:

  1. IBM JRE 1.8.0 编译器合规级别 1.8
n is 272400600
Executed in 1024 miliseconds
  1. Oracle JRE 1.8.0_131 编译器合规级别 1.8
n is 272400600
Executed in 2002 miliseconds
  1. Sun JRE 1.5.0_22 编译器合规级别 1.5
n is 272400600
Executed in 1506 miliseconds

如您所见,Oracle JRE 比 IBM JRE 慢 100%,比 Sun JRE 慢 25%。 Oracle 和 IBM 实现之间的差距很大,而且 Oracle JRE 看起来像是 Sun JRE 的回归。

有没有人解释一下为什么 Java 的“官方”实现这么慢?

我对使用 JMH 没有兴趣,因为我不想对任何东西进行基准测试。

下面是我用来测试的硬件配置:

【问题讨论】:

  • 最好在 JMH 这样的工具中进行测试。不同的 Java 运行时将启动得更快,并在稍后进行优化。例如,循环将被展开,热点将使这些测试几乎毫无意义。即代码运行得越多,它就会越快
  • 你是在测试编译器还是机器?为什么不尝试 n 作为双精度数?所有你需要改变的是 long n = 0;将 n = 0.0 翻倍; (以及打印语句。)顺便说一句:n++ 其中 n 是一个双重作品。
  • @Marichyasana 测试的重点是让不同的类型参与除法。

标签: java performance-testing


【解决方案1】:

首先,我不是性能专家,但我在玩 JMH。

最好在 JMH 之类的工具中进行测试,这样您就可以compare apples with apples

不同的 Java 运行时启动速度会更快,并会在稍后进行优化。例如loop can be unrolled,热点就会启动。

运行一次测试不会为您提供准确的样本。即代码运行得越多,它就会越快。不同的供应商实施了 C1、C2、JIT 和一堆魔法来使代码运行得越来越快。

这些是在 JHM 中创建项目的步骤,希望能帮助您比较苹果和苹果。

  1. 创建一个 JHM 项目:

    mvn -DarchetypeGroupId=org.openjdk.jmh -DarchetypeArtifactId=jmh-java-benchmark-archetype -DarchetypeVersion=1.18 -DarchetypeRepository=http://repo.maven.apache.org/maven2/ -DgroupId=com.yourcompany -DartifactId=HarmonicSeriesTest -Dversion=1.0-SNAPSHOT -Dpackage =com.yourcompany.harmonicseriestest -Darchetype.interactive=false --batch-mode archetype:generate

  2. 构建项目

    cd HarmonicSeriesTest/

    mvn 包

  3. 编辑生成的类

编辑 MyBenchmark.java

import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;

public class MyBenchmark {
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    public double harmonicSeriesTest() {
        final int limit = 20;
        double sum = 0.0;
        long n = 0;
        while (sum < limit) {
            n++;
            sum += 1.0 / n;
        }
        return sum;
    }

}

4。 在命令行而不是 IDE 上运行项目,因为这会影响事情

在命令行执行:

mvn package
cd target
java -jar benchmarks.jar

我的输出。如您所见,第一次迭代很慢,然后又加快了。寻找预热后的第一个迭代,因为这是您应该在 Java 实现和使用不同的 JVM 标志时比较的值。

JMH 1.18 (released 61 days ago)
VM version: JDK 1.8.0_102, VM 25.102-b14
VM invoker: /home/richard/install/java/jdk1.8.0_102/jre/bin/java
VM options: <none>
Warmup: 20 iterations, 1 s each
Measurement: 20 iterations, 1 s each
Timeout: 10 min per iteration
Threads: 1 thread, will synchronize iterations
Benchmark mode: Average time, time/op
Benchmark: com.yourcompany.harmonicseriestest.MyBenchmark.harmonicSeriesTest

Run progress: 0.00% complete, ETA 00:06:40
Fork: 1 of 10
Warmup Iteration   1: 1773.454 ms/op
Warmup Iteration   2: 1782.517 ms/op
Warmup Iteration   3: 1545.739 ms/op
Warmup Iteration   4: 1542.968 ms/op
Warmup Iteration   5: 1530.740 ms/op
Warmup Iteration   6: 1539.304 ms/op
Warmup Iteration   7: 1538.079 ms/op
Warmup Iteration   8: 1535.280 ms/op
Warmup Iteration   9: 1547.716 ms/op
Warmup Iteration  10: 1520.056 ms/op
Warmup Iteration  11: 1503.892 ms/op
Warmup Iteration  12: 1513.037 ms/op
Warmup Iteration  13: 1521.966 ms/op
Warmup Iteration  14: 1519.931 ms/op
Warmup Iteration  15: 1515.179 ms/op
Warmup Iteration  16: 1514.342 ms/op
Warmup Iteration  17: 1525.555 ms/op
Warmup Iteration  18: 1519.022 ms/op
Warmup Iteration  19: 1533.529 ms/op
Warmup Iteration  20: 1525.547 ms/op
Iteration   1: 1524.958 ms/op

NB 这些是用于测试 JVM 的 golden samples。微基准测试很棘手,很容易做出“错误”的测试。

还可以查看Nitsan's 之类的博客和Aleksey Shipilev's 之类的幻灯片,因为他们真的知道自己在做什么:)。

【讨论】:

  • 感谢您的回答。我知道 JMH 并使用它进行了测试。差距更小(~ 1700 ms Oracle vs ~1400 ms IBM 在我的计算机上)所以即使有一个不是 HotSpot 编译器命令兼容 VM 的大警告,IBM 也更快。问题是,在生产中,在 JRE 达到最佳状态之前,我无法“预热”它,这就是为什么 JMH 对我来说并不是非常有用的原因。
  • @Eugen Covaci,我不明白你的意思是“我不能'热身'JRE,直到它达到最佳状态”你是说你希望拥有更多最佳预热版本运行得更快?
  • 您看到的代码与我将在生产中使用的代码接近,只是简化了,这就是为什么我只对按原样进行测试感兴趣。我没有对 JRE 进行基准测试。
  • 您可以将这些标志传递给 JHM 和 java 以加快预热速度。请参阅此stackoverflow.com/questions/1481853/…。对于 JMH java -XX:CompileThreshold=1 -jar benchmarks.jar。 (对于 IBM VM,标志可能不同)
  • 没有帮助,结果相同。
猜你喜欢
  • 2012-08-21
  • 2018-12-21
  • 2015-10-22
  • 2010-09-27
  • 2021-04-10
  • 2011-09-22
  • 2012-02-07
  • 2018-06-29
  • 1970-01-01
相关资源
最近更新 更多