【问题标题】:When will JVM use intrinsicsJVM 什么时候使用内部函数
【发布时间】:2013-11-22 10:14:10
【问题描述】:

为什么在 JVM 内部类中存在的某些代码模式会变成一个内在函数,而从我自己的类中调用的相同模式却不是。

例子:

bitCount 函数,当从 Integer.bitCount(i) 中调用时,将变成一个内在函数。但是当复制到我的班级然后被调用时,将需要更长的时间来执行。

比较

Integer.bitCount(i) 
MyClass.bitCount(i) 


public static int bitCount(int i) {
    // HD, Figure 5-2
    i = i - ((i >>> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
    i = (i + (i >>> 4)) & 0x0f0f0f0f;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    return i & 0x3f;
}

【问题讨论】:

  • 内在方法列表在 JVM 中是硬编码的,因此通过构造,您自己的方法不会在其中...如果您运行您的方法足够长的时间,无论如何它都应该在那里编译不应该与内在...

标签: java performance jvm intrinsics


【解决方案1】:

答案很简单:以这种方式定义内部函数是因为存在一种获取函数结果的更快、本地的方式,并且由于指定的映射而应用它。

这根本与编译无关。 Integer.bitCount 的特殊之处在于实现被标记为可替换为原生 asm 指令 POPCNT。基本上,在使用 Integer.bitCount 函数(如果 CPU 支持该指令)时会使用此本机指令,当您声明自己的函数副本时,将使用正常实现。

为什么JVM能够识别出可以优化的功能?因为它在JDK中硬编码somewhere,所以与代码相似度无关。

【讨论】:

  • @Mark:C 编译器确实可以识别一些模式,例如 (x << n ) | (x >> (32-n)) as a rotate。 JVM 可以将掩码/移位/添加序列识别为 bitCount 并使用理想的实现,但显然您的 JVM 没有该模式的模式识别器。 C 编译器比 Java 更需要这种模式识别,因为 C 没有可移植代码可用于旋转/popcnt/等的单一标准库。
【解决方案2】:

JVM 有一个方法列表,通常是本地方法,用内联机器代码替换。此列表出现在 OpenJDK 的内部头文件中,但我在网络上找不到指向它的链接。

参见@Jack 提供的链接中的第 581 行vmSymbols.hpp

【讨论】:

    猜你喜欢
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-12
    相关资源
    最近更新 更多