JVM的几点性能优化
作者:网络转载 发布时间:[ 2014/4/1 10:21:34 ] 推荐标签:性能优化 JVM
这两个例子的共同之处是,循环体里先是处理这个事情,过一段时间又处理另外一件。编译器可以识别出这些情况,它可以将循环拆分成不同的分支,或者将几次迭代单独剥离。
我们来说下第一个例子。if(i>0)第一次的时候是false,后面一直是true。为什么要每次都判断这个呢?编译器会对它进行优化,好像你是这样写的一样:
StringBuilder sb = new StringBuilder("Ingredients: ");
if (ingredients.length > 0) {
sb.append(ingredients[0]);
for (int i = 1; i < ingredients.length; i++) {
sb.append(", ");
sb.append(ingredients[i]);
}
}
return sb.toString();
这样写的话,多余的if(i > 0)被去掉了,尽管也带来了一些代码重复(两处append),不过性能上得到了提升。
边界条件优化
检查空指针是很常见的一个操作。有时候null是一个有效的值(比如,表明缺少某个值,或者出现错误),有时候检查空指针是为了代码能正常运行。
有些检查是永远不会失败的(在这里null代表失败)。这里有一个典型的场景:
public static String l33tify(String phrase) {
if (phrase == null) {
throw new IllegalArgumentException("phrase must not be null");
}
return phrase.replace('e', '3');
}
如果你代码写得好的话,没有传null值给l33tify方法,这个判断永远不会失败。
在多次执行这段代码并且一直没有进入到if语句之后,JIT编译器会认为这个检查很多可能是多余的。然后它会重新编译这个方法,把这个检查去掉,后代码看起来像是这样的:
public static String l33tify(String phrase) {
return phrase.replace('e', '3');
}
这能显著的提升性能,而且在很多时候这么优化是没有问题的。
那万一这个乐观的假设实际上是错了呢?
JVM现在执行的已经是本地代码了,空引用可不会引起NullPointerException,而是真正的严重的内存访问冲突,JVM是个低级生物,它会去处理这个段错误,然后恢复执行没有优化过的代码——这个编译器可再也不敢认为它是多余的了:它会重新编译代码,这下空指针的检查又回来了。
虚方法内联
JVM的JIT编译器和其它静态编译器的大不同是,JIT编译器有运行时的动态数据,它可以基于这些数据进行决策。
方法内联是编译器一个常见的优化,编译器将方法调用替换成实际调用的代码,以避免一次调用的开销。不过当碰到虚方法调用(动态分发)的话情况需要点小技巧了。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11