Lsion
<dreamlison@163.com>
, v1.0.0
, 2023.04.01
JAVA-编程基础-08-try-catch性能探究
文章目录
- JAVA-编程基础-08-try-catch性能探究
- try-catch会影响性能吗?
try-catch会影响性能吗?
在 for 循环里面搞了个 try-catch
,不知道try-catch
有性能损耗?
for (int i = 0; i < 5000; i++) {
try {
dosth
} catch (Exception e) {
e.printStackTrace();
}
}
需要怎么改呢?有些人回答: try-catch
提到外面啊。
这种回答是错误的:且不说性能这代码的目的明显是让循环内部单次调用出错不影响循环的运行,移到外面,业务逻辑不就变了。
catch 整个 for 循环和在循环内部 catch,在不出错的情况下,其实性能差不多
测试代码:
public class TryCatchTest {
// 用 @Benchmark 注解标记一个方法作为基准测试方法
@Benchmark
public void tryfor(Blackhole blackhole) {
// 使用 try-catch 语句包装一个 for 循环
try {
for (int i = 0; i < 1000; i++) {
// 在循环中调用 Blackhole.consume() 方法
blackhole.consume(i);
}
} catch (Exception e) {
// 捕获异常并打印堆栈跟踪信息
e.printStackTrace();
}
}
// 用 @Benchmark 注解标记另一个方法作为基准测试方法
@Benchmark
public void fortry(Blackhole blackhole) {
// 使用 for 循环包装一个 try-catch 语句
for (int i = 0; i < 1000; i++) {
try {
// 在 try 块中调用 Blackhole.consume() 方法
blackhole.consume(i);
} catch (Exception e) {
// 捕获异常并打印堆栈跟踪信息
e.printStackTrace();
}
}
}
}
请允许我补充一些概念,以便大家能更好的理解这段代码。
第一个:
@Benchmark
是一个来自于 JMH(Java Microbenchmark Harness)库的注解,用来标记一个方法作为基准测试方法。JMH 是一个专门用于编写 Java 微基准测试的工具包,包含了一些用于测试 Java 代码性能和微调 JVM 的工具和库。使用@Benchmark
注解标记的方法将被 JMH 自动识别为基准测试方法,并在运行时进行基准测试。在基准测试期间,JMH 会运行被标记的方法多次,并测量方法的执行时间、吞吐量、延迟等指标,并生成统计结果。第二个:在 JMH 进行基准测试时,为了避免 JIT 编译器优化掉测试代码中的某些操作,我们需要在测试代码中使用一些占位符,以便让编译器认为这些操作是有意义的,不应该被优化掉。
Blackhole.consume()
方法就是这样的一个占位符。它用来占用一些 CPU 时间和内存空间,以确保测试结果的准确性和可靠性。
try-catch
从 for 循环里面提出来跟在for循环里面做个对比跑一下
可以看到,两者的性能(数字越大越好)其实差不多:
第一步,在 pom.xml 文件中加入依赖。
<!-- 引入 JMH 工具包 -->
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.35</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.35</version>
</dependency>
第二步,Intellij IDEA 中安装 JMH 插件。
第三步,在代码编辑器中点击这个带有时间和运行的图标。然后静静等待结果就可以了,本部比较慢(32G内存i9,跑了 分钟,JMH追求公平公正)
使用 javap 查看字节码
tryfor 的字节码
异常表记录的是 0 - 20 行,如果这些行里面的代码出现问题,直接跳到 23 行处理。
fortry的字节码
字节码层面来看,没抛错两者的执行效率其实没啥差别
网上说try-catch会影响性能的说法确实有,在《Effective Java》这本书里就提到了 try-catch
性能问题
总结下有关 try-catch
性能问题说法:
try-catch
相比较没try-catch
,确实有一定的性能影响,但是旨在不推荐我们用try-catch
来代替正常能不用try-catch
的实现,而不是不让用try-catch
。- for循环内用
try-catch
和用try-catch
包裹整个 for 循环性能差不多,但是其实两者本质上是业务处理方式的不同,跟性能扯不上关系,关键看你的业务流程处理。 - 虽然知道
try-catch
会有性能影响,但是业务上不需要避讳其使用,业务实现优先(只要不是书中举例的那种逆天代码就行),非特殊情况下性能都是其次,有意识地避免大范围的try-catch
,只 catch 需要的部分即可(没把握全 catch 也行,代码安全执行第一)。