代码之家  ›  专栏  ›  技术社区  ›  Oscar Gomez

Java try/catch性能,建议尽量减少try子句中的内容吗?

  •  33
  • Oscar Gomez  · 技术社区  · 14 年前

    考虑到你有这样的代码:

    doSomething() // this method may throw a checked a exception
    //do some assignements calculations
    doAnotherThing() //this method may also throw the same type of checked exception
    //more calls to methods and calculations, all throwing the same kind of exceptions.
    

    现在我知道了,在构造异常时,实际上存在性能问题,特别是在展开堆栈时。我也读过几篇文章,指出在进入try/catch块时性能会受到轻微影响,但这些文章似乎都没有任何结论。

    我的问题是,是否建议尽量减少try catch中的行数?,也就是说,只有在try子句中有可以实际抛出您捕获的异常的行try子句中的代码运行速度慢还是导致性能下降?.

    但更重要的是,考虑到这样做,什么是最佳实践/更具可读性的解决方案:

    try {
        doSomething() // this method may throw a checked a exception
    //do some assignements calculations
    doAnotherThing() //this method may also throw the same type of checked exception
    //more calls to methods and calculations, all throwing the same kind of exceptions.
    }
    catch (MyCheckedException e) {
       //handle it
    }
    

    或:

    try {
        doSomething() // this method may throw a checked a exception
    }
    catch (MyCheckedException e) {
       //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
       continue;     
    } 
     //do some assignements calculations
    try {
        doAnotherThing() // this method may throw a checked a exception
    }
    catch (MyCheckedException e) {
        //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
       continue;
    } 
    

    这是在考虑您将以完全相同的方式处理所有这些选中的异常。

    9 回复  |  直到 14 年前
        1
  •  15
  •   rwat    14 年前

    在这里的示例中,真正的性能影响是doSomething()和doAnotherThing()都抛出异常。进入try块很快,直到它抛出异常。

    这真的取决于你的处境。如果您需要在MyCheckedException以任何方式抛出时执行相同的操作,我会认为将它们放在同一个try块中更具可读性和性能,但是如果您需要以不同的方式处理这两种不同的情况,那么将它们分开当然更有意义。

    编辑:我看了你评论的结尾,你假设处理这两个问题的方式相同,在这种情况下,我会把它们放在同一个try块中。

        2
  •  23
  •   user207421    9 年前

    建议保持线路 在试捕范围内达到最低限度?

    不,你怎么能想到 try 块或实际上任何块都可能对性能产生任何影响。

    try子句中的代码 跑得慢一点或引起任何性能 击中?.

    不。

    正如您所观察到的,异常只会在抛出时产生性能成本。

    如果您关心的是“try”性能,那么肯定要做的是将代码保存在 最大值?

        3
  •  4
  •   André Caron    14 年前

    我不知道哪一个慢,但别忘了 try 阻塞是控制流。您应该使控制流与您要完成的任务相匹配。对我来说,选择

    try {
        // op 1.
        // op 2.
        / ...
        // op n.
    }
    catch ( MyCheckedException error )
    {
        // handle any `MyException` in op 1, 2 ... n.
    }
    

    分离 catch 每个块主要是决定我是否要对每个操作执行不同的处理,一直执行到操作 n 不考虑错误,或者尝试执行所有错误并在第一个错误处失败。

    编写干净、可读的代码,以及 然后 寻找瓶颈。如果现有的实验不能得出基本的指导原则,那么我怀疑这不是你能找到瓶颈的地方。

        4
  •  3
  •   gpeche    14 年前

    在任何像样的JVM中,拥有try块基本上都不会产生性能影响。真正的成功发生在实际抛出异常时。

    你可以阅读 this article 为了了解JVM如何在字节码中实现异常处理:它创建“异常表”,将代码区域映射到catch/finally块,因此:

    • try块的字节码与标准{}块的字节码相同
    • 在不抛出的情况下,唯一的额外开销是将“异常表”加载到内存中。

    当然,当抛出一个异常时,会有很多堆栈工作要做,所以会有代价。无论如何,它并没有SEH(NET异常)那么糟糕。

        5
  •  2
  •   Jeroen van Bergen    14 年前

    您的代码应该只处理它可以处理的异常,其他的应该被重新抛出。

    try块中的代码量不会导致速度减慢,命中catch块会导致速度减慢。但是,除非您尝试编写真正的高性能代码,否则我不会担心它。

        6
  •  1
  •   Chris    14 年前

    将try/catch块的数量保持在最小值将稍微提高性能,但是移动工作实际上不会有什么区别,除了由于抛出异常而被跳过的工作。

        7
  •  0
  •   Richard Gomes    14 年前

    异常开销很大,因为每次抛出异常时,都必须创建和填充堆栈跟踪。

    设想一个余额转移操作,在1%的情况下由于资金不足而失败。 即使故障率相对较低,性能也可能受到严重影响。

    查看源代码和基准测试结果 here .

        8
  •  0
  •   Taryn East    10 年前

    我不确定里面 try 阻塞的性能可能很慢,但我知道的是 ex.getStackTrace() 非常慢,因为它显示了所有的命令堆栈,您应该小心处理。

        9
  •  -1
  •   Mike Caron    14 年前

    每个异常块都有开销。所以,你想要最大化你在一个街区中停留的时间。

    但是,您还必须考虑语义上的差异。在第一个例子中,如果 doSomething() 抛出异常,然后 doAnotherThing() 不会跑的。在第二个示例中(假设catch处理程序不返回), 不做任何事() 将运行。