JIT编译器优化:使用相同参数

时间:2017-01-14 19:09:19

标签: java validation optimization parameters jit

假设我有一个方法用于验证特定值,例如方法isEven

public static boolean isEven(int evenSize) {
    return evenSize % 2 == 0;
}

我使用此方法验证外部输入(例如来自磁盘或来自用户)。但之后我也在一个需要偶数值的方法中使用这个方法:

public static String padToEven(int evenSize, String string) {
    if (!isEven(evenSize)) { // <-- duplication of isEven method
        throw new IllegalArgumentException("evenSize argument is not even");
    }

    if (string.length() >= evenSize) {
        return string;
    }

    StringBuilder sb = new StringBuilder(evenSize);
    sb.append(string);
    for (int i = string.length(); i < evenSize; i++) {
        sb.append('x');
    }
    return sb.toString();
}

所以基本上我们向padToEven()提供已经验证的参数,并使用相同的isEven函数验证参数。 JIT编译器(比如Java的第8版)是否可以找到第二个调用并将其优化掉?

您可以假设检查不依赖于动态值(即,它对所提供的参数值是确定的)。除了返回值之外,它也没有任何副作用,例如记录语句。

1 个答案:

答案 0 :(得分:2)

我不认为Java会进行任何过程间分析。但是,该方法有可能被内联。当你内联所有内容时,那就是

if (evenSize % 2 != 0) {
    throw new IllegalArgumentException("evenSize argument is not even");
}
... some code not changing evenSize
if (evenSize % 2 != 0) {
    throw new IllegalArgumentException("evenSize argument is not even");
}

这是非常简单的优化。这种内联不是你可以依赖的东西,因为有一个内联限制可以很快达到。

其他优化

OTOH,测试非常简单,可能会优化到

public static boolean isEven(int evenSize) {
    return (evenSize & 1) == 0;
}

使用更快的操作。但这并不是我所关心的事情(因为有许多其他代码,所以你不能获得太多)。

我想,最好的优化是消除StringBuilder。什么???是的,严肃地说,char[]会这样做:

char[] result = new char[evenSize];
for (int i = 0; i < string.length(); i++) {
    result[i] = string.charAt(i);
}
for (int i = string.length(); i < evenSize; i++) {
    result[i] = 'x';
}
return new String(result);

前段时间,我做了一些测量表明它应该更快。最近的JIT可能已经改变了。不是重要的部分:

这里有什么优化意义?

完全没有。除非你

  • 确实需要提高性能
  • 描述它并找到罪魁祸首
  • 准备花一些时间进行基准测试和分析

不要这样做。幸运的是,JIT采用简短的方法针对干净的代码进行了优化。它无法改善您的算法和数据结构,因此您可以在需要时进行优化。微观优化的回报要小得多。

您的上述代码很好,请勿触摸它。

相关问题