¿Qué pasa con los problemas de rendimiento de Try-Catch?

"Sí, miraste este código fantasma e incluso hiciste un bucle for try-catch, ¿no sabes try-catchque hay una pérdida de rendimiento?" El viejo Chen señaló el código en la pantalla con seriedad:

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

Asomé la cabeza para mirar el código, "Viejo Chen, ¿cómo crees que debería cambiarse?"

"¡Por supuesto que es para try-catchsacarlo a relucir!", Soltó Lao Chen sin siquiera pensarlo.

"¿Eres estúpido? Dejando de lado el rendimiento, el propósito de este código es obviamente hacer que un solo error de llamada dentro del ciclo no afecte el funcionamiento del ciclo. ¡Si sales, la lógica comercial cambiará!"

El viejo Chen rascó su Mediterráneo, "¡Parece ser lo mismo!"

"Mirando hacia atrás, captura todo el ciclo for y captura dentro del ciclo, si no hay ningún error , el rendimiento es realmente el mismo" Tomé un sorbo de café y lo mencioné casualmente, listo para mostrárselo frente a Lao Chen.

"¿Qué quieres decir?", Lao Chen me miró un poco confundido, " try-catchHay una pérdida de rendimiento, ¡he leído la información en Internet!"

Efectivamente, Lao Chen mordió el anzuelo, abrí la idea sin decir una palabra y escribí el siguiente código en una sola operación:

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 no es tan bueno como mostrar código. ¿Viste eso, Lao Chen? Lo try-catchsacaré bucle for y lo compararé con el bucle for. Adivina cuál es la diferencia entre los dos".

"Corta, estoy seguro de que Tryfor funciona bien, ni siquiera lo pienses, si no, ¡me lavaré el cabello al revés!", Prometió el viejo Chen.

Era demasiado perezoso para BB con él, y comencé el punto de referencia directamente.Los resultados de la ejecución son los siguientes:

Se puede ver que el rendimiento de los dos (cuanto mayor sea el número, mejor) es en realidad similar:

  • arrepentimiento: 86,261(100359-14098) ~ 114,457(100359+14098)
  • prueba por: 95,961 (103216-7255) ~ 110,471 (103216 + 7255)

Luego ajusté la cantidad de bucles for a 1000 (la cantidad de bucles for en escenarios comerciales generales no será mucha), y el resultado es similar:

El viejo Chen parecía estupefacto: "¿Qué pasa con el impacto en el rendimiento? ¿Por qué se ha ido?"

我直接一个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,我们下篇见~

Supongo que te gusta

Origin juejin.im/post/7204121228016091197
Recomendado
Clasificación