假设我有一个用于验证特定值的方法,例如方法 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 中)是否有可能找到第二个调用并将其优化掉?
您可以假设检查不依赖于动态值(即它对提供的参数值是确定性的)。除了返回值(例如日志语句)之外,它也没有任何副作用。
最佳答案
我认为 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 针对具有短方法的干净代码进行了优化。它无法改进您的算法和数据结构,因此您可以在真正需要时进行优化。微观优化的返回要低得多。
你上面的代码很好,不要碰它。
关于java - JIT编译器优化: second method call with same parameter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41653877/