Was ist mit Try-Catch-Leistungsproblemen?

„Ja, du hast dir diesen Geistercode angesehen und sogar eine for-Schleife gemacht try-catch, weißt du nicht, try-catchdass es einen Leistungsverlust gibt?“ Old Chen zeigte ernsthaft auf den Code auf dem Bildschirm:

 for (int i = 0; i < 5000; i++) {
     try {
         dosth
     } catch (Exception e) {
         e.printStackTrace();
     }
 }
复制代码

Ich streckte meinen Kopf hinüber, um mir den Code anzusehen, "Alter Chen, wie denkst du, sollte er geändert werden?"

„Natürlich, um es try-catchherauszubringen !“, platzte Lao Chen heraus, ohne auch nur darüber nachzudenken.

"Sind Sie dumm? Abgesehen von der Leistung besteht der Zweck dieses Codes offensichtlich darin, dass ein einzelner Anruffehler innerhalb der Schleife den Lauf der Schleife nicht beeinflusst. Wenn Sie nach draußen gehen, ändert sich die Geschäftslogik!"

Old Chen kratzte an seinem Mittelmeer, "Es scheint dasselbe zu sein!"

„Wenn Sie zurückblicken, fangen Sie die gesamte for-Schleife und fangen Sie innerhalb der Schleife, wenn es keinen Fehler gibt , ist die Leistung tatsächlich dieselbe.“ Ich nahm einen Schluck Kaffee und erwähnte es beiläufig, bereit, es Lao Chen zu zeigen.

„Was meinst du damit?“ Lao Chen sah mich etwas verwirrt an, „ try-catchEs gibt einen Leistungsverlust, ich habe die Informationen im Internet gelesen!“

Tatsächlich nahm Lao Chen den Köder, ich öffnete die Idee, ohne ein Wort zu sagen, und tippte den folgenden Code in einem Vorgang ein:

public class TryCatchTest {

    @Benchmark
    public void tryfor(Blackhole blackhole) {
        try {
            for (int i = 0; i < 5000; i++) {
                blackhole.consume(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Benchmark
    public void fortry(Blackhole blackhole) {
        for (int i = 0; i < 5000; i++) {
            try {
                blackhole.consume(i);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
复制代码

„BB ist nicht so gut wie Show-Code. Hast du das gesehen, Lao Chen, ich nehme es try-catchaus for-Schleife und vergleiche es mit der for-Schleife. Ratet mal, was der Unterschied zwischen den beiden ist?“

„Schnitt, ich bin mir sicher, Tryfor funktioniert gut, denk nicht einmal darüber nach, wenn nicht, wasche ich meine Haare verkehrt herum!“, schwor der alte Chen.

Ich war zu faul zum BB mit ihm und habe direkt den Benchmark gestartet, die Ergebnisse des Runs sind wie folgt:

Es ist ersichtlich, dass die Leistung der beiden (je größer die Zahl, desto besser) tatsächlich ähnlich ist:

  • Bedauern: 86.261 (100359-14098) ~ 114.457 (100359+14098)
  • tryfor: 95.961(103216-7255) ~ 110.471(103216+7255)

Ich habe dann die Anzahl der for-Schleifen auf 1000 reduziert (die Anzahl der for-Schleifen in allgemeinen Geschäftsszenarien wird nicht hoch sein), und das Ergebnis ist ähnlich:

Old Chen sah verblüfft aus: „Was ist mit der Auswirkung auf die Leistung? Warum ist es weg?“

我直接一个javap,让老陈看看,其实两个实现在字节码层面没啥区别:

tryfor 的字节码

异常表记录的是 0 - 20 行,如果这些行里面的代码出现问题,直接跳到 23 行处理

fortry 的字节码

差别也就是异常表的范围小点,包的是 9-14 行,其它跟 tryfor 都差不多。

所以从字节码层面来看,没抛错两者的执行效率其实没啥差别。

“那为什么网上流传着try-catch会有性能问题的说法啊?”老陈觉得非常奇怪。

这个说法确实有,在《Effective Java》这本书里就提到了 try-catch 性能问题:

并且还有下面一段话:

正所谓听话不能听一半,以前读书时候最怕的就是一知半解,因为完全理解选择题能选对,完全不懂蒙可能蒙对,一知半解必定选到错误的选项!

《Effective Java》书中说的其实是不要用 try-catch 来代替正常的代码,书中的举例了正常的 for 循环肯定这样实现:

但有个卧龙偏偏不这样实现,要通过 try-catch 拐着弯来实现循环:

这操作我只能说有点逆天,这两个实现的对比就有性能损耗了

我们直接再跑下有try-catch 的代码和没 try-catch的 for 循环区别,代码如下:

结果如下:

+-差不多,直接看前面的分数对比,没有 try-catch 的性能确实好些,这也和书中说的 try-catch 会影响 JVM 一些特定的优化说法吻合,但是具体没有说影响哪些优化,我猜测可能是指令重排之类的。

好了,我再总结下有关 try-catch 性能问题说法:

  1. try-catch 相比较没 try-catch,确实有一定的性能影响,但是旨在不推荐我们用 try-catch 来代替正常能不用 try-catch 的实现,而不是不让用 try-catch
  2. for循环内用 try-catch 和用 try-catch 包裹整个 for 循环性能差不多,但是其实两者本质上是业务处理方式的不同,跟性能扯不上关系,关键看你的业务流程处理。
  3. 虽然知道try-catch会有性能影响,但是业务上不需要避讳其使用,业务实现优先(只要不是书中举例的那种逆天代码就行),非特殊情况下性能都是其次,有意识地避免大范围的try-catch,只 catch 需要的部分即可(没把握全 catch 也行,代码安全执行第一)。

“好了,老陈你懂了没?”

“行啊yes,BB是一套一套的,走请你喝燕麦拿铁!” 老陈一把拉起我,我直接一个挣脱,“少来,我刚喝过咖啡,你那个倒立洗头,赶紧的!”我立马意识到老陈想岔开话题。

“洗洗洗,我们先喝个咖啡,晚上回去给你洗!”

晚上22点,老陈发来一张图片:

你别说,这头发至少比三毛多。

我是yes,我们下篇见~

Ich denke du magst

Origin juejin.im/post/7204121228016091197
Empfohlen
Rangfolge