Java循环在某些运行/ JIT的错误之后变慢了吗?

明显死亡

因此,我想对一些基本的Java功能进行基准测试,以为该问题添加一些信息:将方法声明为static有什么好处

我知道编写基准测试有时并不容易,但是在这里发生的事情我无法解释。

请注意,我对如何解决此问题不感兴趣,但对为什么会发生*

测试类:

public class TestPerformanceOfStaticVsDynamicCalls {

    private static final long RUNS = 1_000_000_000L;

    public static void main( String [] args ){

        new TestPerformanceOfStaticVsDynamicCalls().run();
    }

    private void run(){

        long r=0;
        long start, end;

        for( int loop = 0; loop<10; loop++ ){

            // Benchmark

            start = System.currentTimeMillis();
            for( long i = 0; i < RUNS; i++ ) {
                r += addStatic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Static: " + ( end - start ) + " ms" );

            start = System.currentTimeMillis();
            for( long i = 0; i < RUNS; i++ ) {
                r += addDynamic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Dynamic: " + ( end - start ) + " ms" );

            // Do something with r to keep compiler happy
            System.out.println( r );

        }

    }


    private long addDynamic( long a, long b ){

        return a+b;
    }

    private static long addStatic( long a, long b ){

        return a+b;
    }

}

我期望第一个循环可以进行预热,而随后的循环可以更快。

在Eclipse中运行它会产生一些奇怪的结果:

Static: 621 ms
Dynamic: 631 ms
1000000001000000000
Static: 2257 ms
Dynamic: 2501 ms
2000000002000000000
Static: 2258 ms
Dynamic: 2469 ms
3000000003000000000
Static: 2231 ms
Dynamic: 2464 ms
4000000004000000000

那么wtf?它变慢了。为了进行交叉检查,我使用java / c 7运行了相同的代码:

Static: 620 ms
Dynamic: 627 ms
1000000001000000000
Static: 897 ms
Dynamic: 617 ms
2000000002000000000
Static: 901 ms
Dynamic: 615 ms
3000000003000000000
Static: 888 ms
Dynamic: 616 ms
4000000004000000000

因此,在以下循环中,只有静态调用变慢了。如果将代码重新安排为仅r在最终循环之后才打印则更奇怪了,我在Eclipse中得到了以下代码

Static: 620 ms
Dynamic: 635 ms
Static: 2285 ms
Dynamic: 893 ms
Static: 2258 ms
Dynamic: 900 ms
Static: 2280 ms
Dynamic: 905 ms
4000000004000000000

而在Java / C 7中:

Static: 620 ms
Dynamic: 623 ms
Static: 890 ms
Dynamic: 614 ms
Static: 890 ms
Dynamic: 616 ms
Static: 886 ms
Dynamic: 614 ms
4000000004000000000

同时在Eclipse中更改动态/静态基准测试的顺序:

Dynamic: 618 ms
Static: 626 ms
1000000001000000000
Dynamic: 632 ms
Static: 2524 ms
2000000002000000000
Dynamic: 617 ms
Static: 2528 ms
3000000003000000000
Dynamic: 622 ms
Static: 2506 ms
4000000004000000000

在Java / C 7中:

Dynamic: 625 ms
Static: 646 ms
1000000001000000000
Dynamic: 2470 ms
Static: 633 ms
2000000002000000000
Dynamic: 2459 ms
Static: 635 ms
3000000003000000000
Dynamic: 2464 ms
Static: 645 ms
4000000004000000000

那么这里发生了什么?

编辑:一些系统信息:

Java version "1.7.0_55"
OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1ubuntu1)
OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode)

Intel(R) Core(TM) i7-2720QM CPU @ 2.20GHz

编辑2:

使用Java8:

Static: 620 ms
Dynamic: 624 ms
1000000001000000000
Static: 890 ms
Dynamic: 618 ms
2000000002000000000
Static: 891 ms
Dynamic: 616 ms
3000000003000000000
Static: 892 ms
Dynamic: 617 ms
4000000004000000000

其他代码顺序在此处产生类似的奇怪(但其他)结果。

脂蛋白

序言:手动编写微基准几乎注定会失败。
有些框架已经解决了常见的基准测试问题。

  1. JIT编译单元是一种方法。将多个基准测试整合到一个方法中会导致无法预测的结果。

  2. JIT严重依赖于执行配置文件,即运行时统计信息。如果某个方法长时间运行第一个方案,JIT将为其优化生成的代码。当该方法突然切换到另一个方案时,不要指望它以相同的速度运行。

  3. JIT可能会跳过优化未执行的代码。它将为该代码留下一个不常见的陷阱。如果遇到陷阱,JVM将取消优化已编译的方法,切换到解释器,然后使用新知识重新编译代码。例如,当您的方法run在第一个热循环中首次编译时,JIT尚不知道System.out.println一旦执行完成println,较早的编译代码很可能会被优化。

  4. 方法越大,为JIT编译器进行优化就越难。例如,似乎没有足够的备用寄存器来容纳所有局部变量。这就是您的情况。

综上所述,您的基准测试似乎通过了以下情形:

  1. 第一个热循环(addStatic)触发run方法的编译执行概要除了addStatic方法外什么都不知道
  2. System.out.println触发去优化,然后第二个热循环(addDynamic)导致run方法重新编译
  3. 现在执行配置文件仅包含有关的信息addDynamic,因此JIT优化了第二个循环,而第一个循环似乎有额外的寄存器溢出:

优化循环:

0x0000000002d01054: add    %rbx,%r14
0x0000000002d01057: add    $0x1,%rbx          ;*ladd
                                              ; - TestPerformanceOfStaticVsDynamicCalls::addDynamic@2
                                              ; - TestPerformanceOfStaticVsDynamicCalls::run@105

0x0000000002d0105b: add    $0x1,%r14          ; OopMap{rbp=Oop off=127}
                                              ;*goto
                                              ; - TestPerformanceOfStaticVsDynamicCalls::run@116

0x0000000002d0105f: test   %eax,-0x1c91065(%rip)        # 0x0000000001070000
                                              ;*lload
                                              ; - TestPerformanceOfStaticVsDynamicCalls::run@92
                                              ;   {poll}
0x0000000002d01065: cmp    $0x3b9aca00,%rbx
0x0000000002d0106c: jl     0x0000000002d01054

循环产生额外的寄存器溢出:

0x0000000002d011d0: mov    0x28(%rsp),%r11  <---- the problem is here
0x0000000002d011d5: add    %r10,%r11
0x0000000002d011d8: add    $0x1,%r10
0x0000000002d011dc: add    $0x1,%r11
0x0000000002d011e0: mov    %r11,0x28(%rsp)    ;*ladd
                                              ; - TestPerformanceOfStaticVsDynamicCalls::addStatic@2
                                              ; - TestPerformanceOfStaticVsDynamicCalls::run@33

0x0000000002d011e5: mov    0x28(%rsp),%r11  <---- the problem is here
0x0000000002d011ea: add    $0x1,%r11          ; OopMap{[32]=Oop off=526}
                                              ;*goto
                                              ; - TestPerformanceOfStaticVsDynamicCalls::run@44

0x0000000002d011ee: test   %eax,-0x1c911f4(%rip)        # 0x0000000001070000
                                              ;*goto
                                              ; - TestPerformanceOfStaticVsDynamicCalls::run@44
                                              ;   {poll}
0x0000000002d011f4: cmp    $0x3b9aca00,%r10
0x0000000002d011fb: jl     0x0000000002d011d0  ;*ifge
                                              ; - TestPerformanceOfStaticVsDynamicCalls::run@25

PS以下JVM选项对于分析JIT编译很有用:

-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:+PrintAssembly -XX:CompileOnly=TestPerformanceOfStaticVsDynamicCalls

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

MATLAB-由于内容类型检查,“ webread”变慢了吗?

来自分类Dev

自python 2.7以来I / O变慢了吗?

来自分类Dev

CPU内核间的通讯速度变慢了吗?

来自分类Dev

与Java 7相比,Java 8中的GC明显变慢了

来自分类Dev

在Linux上运行的Java应用在某些网站上遇到SSL握手错误

来自分类Dev

当使用$ AddUnixListenSocket时,rsyslog向远程发送数据的速度变慢了吗?

来自分类Dev

为什么在这段代码中的 if 语句之后没有运行 java 脚本循环?

来自分类Dev

Java 1.7 / 1.8 JIT编译器坏了吗?

来自分类Dev

Java for loop / jvm损坏了吗?!?循环内的递增运算符在1之后不递增

来自分类Dev

循环运行时发生Java逻辑错误:If / else计数器计数错误

来自分类Dev

For循环变慢

来自分类Dev

在派生类构造函数之后运行某些东西

来自分类Dev

条件语句/循环错误:某些元素是否同时未达到?

来自分类Dev

条件语句/循环错误:某些元素是否同时未达到?

来自分类Dev

for循环的C运行时错误

来自分类Dev

运行时无限循环错误

来自分类Dev

运行“ npm start”时发生循环错误?

来自分类Dev

for循环的C运行时错误

来自分类Dev

php编程错误(无法运行while循环)

来自分类Dev

运行for循环时出现奇怪的运行时错误'424'

来自分类Dev

如何运行多个while循环,这些循环在每个循环之后关闭?

来自分类Dev

如何运行多个while循环,这些循环在每个循环之后关闭?

来自分类Dev

RPi java运行错误

来自分类Dev

循环搜索并显示数组Java的某些部分

来自分类Dev

从某些元素开始的LinkedHashSet循环(Java)。

来自分类Dev

对理解某些for循环有帮助吗?(java)

来自分类Dev

For 循环不在 Java 中运行

来自分类Dev

简单的Java代码中的某些错误

来自分类Dev

我的Ubuntu 12.04 LTS变慢了

Related 相关文章

  1. 1

    MATLAB-由于内容类型检查,“ webread”变慢了吗?

  2. 2

    自python 2.7以来I / O变慢了吗?

  3. 3

    CPU内核间的通讯速度变慢了吗?

  4. 4

    与Java 7相比,Java 8中的GC明显变慢了

  5. 5

    在Linux上运行的Java应用在某些网站上遇到SSL握手错误

  6. 6

    当使用$ AddUnixListenSocket时,rsyslog向远程发送数据的速度变慢了吗?

  7. 7

    为什么在这段代码中的 if 语句之后没有运行 java 脚本循环?

  8. 8

    Java 1.7 / 1.8 JIT编译器坏了吗?

  9. 9

    Java for loop / jvm损坏了吗?!?循环内的递增运算符在1之后不递增

  10. 10

    循环运行时发生Java逻辑错误:If / else计数器计数错误

  11. 11

    For循环变慢

  12. 12

    在派生类构造函数之后运行某些东西

  13. 13

    条件语句/循环错误:某些元素是否同时未达到?

  14. 14

    条件语句/循环错误:某些元素是否同时未达到?

  15. 15

    for循环的C运行时错误

  16. 16

    运行时无限循环错误

  17. 17

    运行“ npm start”时发生循环错误?

  18. 18

    for循环的C运行时错误

  19. 19

    php编程错误(无法运行while循环)

  20. 20

    运行for循环时出现奇怪的运行时错误'424'

  21. 21

    如何运行多个while循环,这些循环在每个循环之后关闭?

  22. 22

    如何运行多个while循环,这些循环在每个循环之后关闭?

  23. 23

    RPi java运行错误

  24. 24

    循环搜索并显示数组Java的某些部分

  25. 25

    从某些元素开始的LinkedHashSet循环(Java)。

  26. 26

    对理解某些for循环有帮助吗?(java)

  27. 27

    For 循环不在 Java 中运行

  28. 28

    简单的Java代码中的某些错误

  29. 29

    我的Ubuntu 12.04 LTS变慢了

热门标签

归档