java方法:java.lang.Integer.numberOfLeadingZeros(int)可以进行优化

时间:2017-10-12 09:25:03

标签: java jvm openjdk jvm-hotspot

原始代码是:

public static int numberOfLeadingZeros(int i) {
    // HD, Figure 5-6
    if (i == 0)
        return 32;
    int n = 1;
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    n -= i >>> 31;
    return n;
}

我认为它可以优化,应该添加以下条件:

if (i < 0)
        return 0;

完全优化的代码是:

public static int numberOfLeadingZeros(int i) {
    if(i<=0) {
        return i < 0 ? 0 : 32;
    }
    int n = 1;
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    n -= i >>> 31;
    return n;
}

3 个答案:

答案 0 :(得分:5)

In theory yes, your suggestion makes sense.

In practice, unless you use an exotic JVM, it will not make any difference because the method is intrinsic, so the code that is executed is not the code you can find in the Java class.

For example on x86/64 cpus, the code is here and uses the bsrl CPU instruction, which is as fast as you can hope for.

答案 1 :(得分:2)

除了这种方法很可能被热点的内在操作所取代之外,如果数字是负数,这种负数检查只是一种改进。对于正数,只需要评估附加条件

因此,此优化的价值取决于此函数的负参数的可能性。当我考虑这个函数的典型用例时,我会将负值视为一个极端情况,而不是典型的参数。

请注意,开头的零特殊处理不是优化,而是一个要求,因为算法在没有特殊处理的情况下不会返回零的正确结果。

由于您的错误报告产生了找到替代方案(也显示在您更新的问题中),这改善了负数情况而不影响正数情况的性能,因为它融合了所需的零测试和负数测试单个预测试,没有什么可以阻止建议的优化。

答案 2 :(得分:1)

已在oracle bug数据库上创建了Bug:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8189230