【问题标题】:understanding code generated by Java hotspot JIT for float test了解 Java 热点 JIT 为浮点测试生成的代码
【发布时间】:2015-01-04 20:00:15
【问题描述】:

我注意到我的一个数字运算程序中的一些看似无辜的 if 语句显着减慢了执行速度(JRE 1.8.25,64 位 Hotspot build 25.25-b02,Intel 64 位 CPU)。

我检查了 JIT 编译器生成的代码,它看起来有点奇怪。下面是一个简单的函数来说明问题:

private float test(float a,float b) {
    float c=a+b;
    if(c<0) {
        return -1;
    }
    return 0;
}

这是生成代码中有趣的部分:

...
0x2bd17ae: vaddss  xmm0,xmm0,xmm1
0x2bd17b2: vxorps  xmm1,xmm1,xmm1
0x2bd17b6: vucomiss xmm0,xmm1
0x2bd17ba: mov     esi,1h
0x2bd17bf: jp      2bd17d8h
0x2bd17c5: jnbe    2bd17d8h
0x2bd17cb: mov     esi,0h
0x2bd17d0: je      2bd17d8h
0x2bd17d6: dec     esi               ;*fcmpg
0x2bd17d8: cmp     esi,0h
0x2bd17db: mov     rsi,57448760h     ; {metadata(method data for {method} ...}
0x2bd17e5: mov     rdi,108h
0x2bd17ef: jnl     2bd17ffh
0x2bd17f5: mov     rdi,118h
0x2bd17ff: mov     rbx,qword ptr [rsi+rdi]
0x2bd1803: lea     rbx,[rbx+1h]
0x2bd1807: mov     qword ptr [rsi+rdi],rbx
0x2bd180b: jnl     2bd1c1fh          ;*ifge
...
// straightforward code for "return -1f" and "return 0f" follows
...

从 0x2bd17ba 到 0x2bd1807 的代码对我来说没有多大意义。为什么会在那里?知道它的作用吗?

编辑:考虑一下,它可能是 JIT 编译器添加的一些代码来收集运行时统计信息(只是因为“元数据”注释而猜测)。但问题是:为什么会存在?我已经调用了这个方法几百万次,所以我认为代码应该已经达到了最终的优化形式。

【问题讨论】:

    标签: java assembly jit disassembly jvm-hotspot


    【解决方案1】:

    (v)ucomiss 设置标志如下:

    unordered    zf,pf,cf = 111
    greater      zf,pf,cf = 000
    less than    zf,pf,cf = 001
    equal        zf,pf,cf = 100
    

    所以这段代码:

        mov     esi,1h
        jp      label  ; if unordered, or
        jnbe    label  ; if greater than, keep it at 1
        mov     esi,0h
        je      label  ; if equal, make 0
        dec     esi    ; otherwise -1
    label:
    

    使esi = 1(如果无序或更大)、esi = 0(如果相等)、esi = -1(如果更小)

    然后它将esi与0进行比较,标记为“ifge”的行确实​​通过检查esi不小于0来检查“如果大于或等于”(有点,也包括无序的情况),所以分支的“其他”部分。

    从 0x2bd17db 到 0x2bd1807 的部分有条件地增加两个计数器,一个或另一个,取决于分支采用的方式。所以这是某种分析。也许以后会用于优化,但我不知道(不过你还会用它来做什么)。

    他们本来可以这样做的:

    vaddss  xmm0,xmm0,xmm1
    vxorps  xmm1,xmm1,xmm1
    vcmpss  xmm0,xmm1,1
    vandps  xmm0,xmm0,[rel negative_one]
    ret
    

    没有分析,但是没有分支,所以没有什么可以分析的。

    【讨论】:

    • 感谢esi标志的解释。在看到您的答案之前,我已经推测了与优化或分析的一些联系(请参阅编辑)。但是我仍然想知道在调用该函数超过 1000 万次之后计数器是否仍然存在。这些东西不应该最终被删除吗?它确实比预期的要慢得多。
    • @RmS 我希望它最终会消失,如果它只是永久地减慢你的速度,那么分析有点错过了重点。不过,我不知道有关 HotSpot 的详细信息。也许尝试更多的迭代?
    • 调用了 2 亿次,仍然存在(即使在调用者的内联版本中)。我想知道这是一个 HotSpot 错误还是只是调试输出的一个工件。运行时测量(显着减慢)表明前者。
    • 我明白你的意思,HotSpot 的部分确实看起来有点未优化。
    猜你喜欢
    • 2013-02-26
    • 2011-12-12
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-02
    相关资源
    最近更新 更多