`
muzi666boy
  • 浏览: 9723 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

try-catch会影响程序性能吗

    博客分类:
  • java
阅读更多
Try-Catch真的会影响程序性能吗
今天和TL争论try-catch使用上的问题,是否为了代码看上去的美观而把该方法下得所有代码都放到try-catch中,我理所当然的持反对意见,但对try-catch的实现机制没有深入研究过,不能说出有说服力的理由,今天在网上找到个.net的try-catch分析,和大家分享下
    很多帖子都分析过Try-Catch的机制,以及其对性能的影响。
   但是并没有证据证明,Try-Catch过于损耗了系统的性能,尤其是在托管环境下。记得园子里有位网友使用StopWatch分析过Try-Catch在不同情况下,与无Try-Catch的代码相比,代码运行的时间指标,结果并没有很大差异。
    下面我来结合IL分析一下Try-Catch吧。
    ● 机制分析
    .Net 中基本的异常捕获与处理机制是由try…catch…finally块来完成的,它们分别完成了异常的监测、捕获与处理工作。一个try块可以对应零个或多个catch块,可以对应零个或一个finally块。不过没有catch的try似乎没有什么意义,如果try对应了多个catch,那么监测到异常后,CLR会自上而下搜索catch块的代码,并通过异常过滤器筛选对应的异常,如果没有找到,那么CLR将沿着调用堆栈,向更高层搜索匹配的异常,如果已到堆栈顶部依然没有找到对应的异常,就会抛出未处理的异常了,这时catch块中的代码并不会被执行。所以距离try最近的catch块将最先被遍历到。
    如有以下代码:
    try
   {
       Convert.ToInt32("Try");
   }
       catch (FormatException ex1)
   {
       string CatchFormatException = "CatchFormatException";
   }
       catch (NullReferenceException ex2)
   {
       string CatchNullReferenceException = "CatchNullReferenceException";
   }
   finally
   {
       string Finally = "Finally";
   }
  对应IL如下:
.method private hidebysig instance void Form1_Load(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// Code size 53 (0x35)
.maxstack 1
.locals init ([0] class [mscorlib]System.FormatException ex1,
[1] string CatchFormatException,
[2] class [mscorlib]System.NullReferenceException ex2,
[3] string CatchNullReferenceException,
[4] string Finally)
IL_0000: nop
IL_0001: nop
IL_0002: ldstr "Try"
IL_0007: call int32 [mscorlib]System.Convert::ToInt32(string)
IL_000c: pop
IL_000d: nop
IL_000e: leave.s IL_0026
IL_0010: stloc.0
IL_0011: nop
IL_0012: ldstr "CatchFormatException"
IL_0017: stloc.1
IL_0018: nop
IL_0019: leave.s IL_0026
IL_001b: stloc.2
IL_001c: nop
IL_001d: ldstr "CatchNullReferenceException"
IL_0022: stloc.3
IL_0023: nop
IL_0024: leave.s IL_0026
IL_0026: nop
IL_0027: leave.s IL_0033
IL_0029: nop
IL_002a: ldstr "Finally"
IL_002f: stloc.s Finally
IL_0031: nop
IL_0032: endfinally
IL_0033: nop
IL_0034: ret
IL_0035:
// Exception count 3
.try IL_0001 to IL_0010 catch [mscorlib]System.FormatException handler IL_0010 to IL_001b
.try IL_0001 to IL_0010 catch [mscorlib]System.NullReferenceException handler IL_001b to IL_0026
.try IL_0001 to IL_0029 finally handler IL_0029 to IL_0033
} // end of method Form1::Form1_Load
    末尾的几行代码揭示出IL是怎样处理异常处理的。最后三行的每一个Item被称作Exception Handing Clause,EHC组成Exception Handing Table,EHT与正常代码之间由ret返回指令隔开。
    可以看出,FormatException排列在EHT的第一位。
    当代码成功执行或反之而返回后,CLR会遍历EHT:
    1. 如果抛出异常, CLR会根据抛出异常的代码的“地址”找到对应的EHC(IL_0001 to IL_0010为检测代码的范围),这个例子中CLR将找到2条EHC, FormatException会最先被遍历到,且为适合的EHC。
    2. 如果返回的代码地址在IL_0001 to IL_0029内,那么还会执行finally handler 即IL_0029 to IL_0033中的代码,不管是否因成功执行代码而返回。
    事实上,catch与finally的遍历工作是分开进行的,如上文所言,CLR首先做的是遍历catch,当找到合适的catch块后,再遍历与之对应finally;而且这个过程会递归进行至少两次,因为编译器将C#的try…catch…finally翻译成IL中的两层嵌套。
当然如果没有找到对应的catch块,那么CLR会直接执行finally,然后立即中断所有线程。Finally块中的代码肯定会被执行,无论try是否检测到了异常。
    ● 改进建议
    由上面的内容可以得出:
    如果使用了“Try-Catch”,且捕获到了异常,CLR做的只不过是遍历Exception Handing Table中的Catch项;然后再次遍历Exception Handing Table中的Finally项,所用时间几乎都花费在遍历Exception Handing Table上;而如果没有捕获到异常,CLR只是遍历Exception Handing Table中的Finally项,所需时间微乎其微。
    而“Try-Catch”遍历后的执行对应操作所用时间,则根据你的具体代码所定,“Try-Catch”引起的只是监控与触发,不应将这部分的代码时间也算“Try-Catch”的消耗。
    所以,可以从性能和代码评审两方面考虑,一般建议有以下几点准则:
    1.尽量给CLR一个明确的异常信息,不要使用Exception去过滤异常
    2.尽量不要将try…catch写在循环中
    3. try尽量少的代码,如果有必要可以使用多个catch块,并且将最有可能抛出的异常类型,书写在距离try最近的位置
    4.不要只声明一个Exception对象,而不去处理它。这样做白白增加了Exception Handing Table的长度。
    5.使用性能计数器实用工具的“CLR Exceptions”检测异常情况,并适当优化
    6.使用成员的Try-Parse模式,如果抛出异常,那么用false代替它
    结论,Try-Catch虽然会消费一点时间,但程序人员大可不必谈虎色变,通过上面的分析,与其说“Try-Catch”会损耗或影响性能,不如说“Try-Catch”与其他代码一样,只是性能的普通消费者,但出于代码书写评审方面的考虑,还是尽量关照一下“Try-Catch”吧。
分享到:
评论

相关推荐

    C#中Try-Catch语句真的影响程序性能吗?

    然而,关于Try-Catch语句是否会影响程序性能的问题,一直是开发者们关注的焦点。本文将结合IL(中间语言)分析Try-Catch的内部机制及其对性能的影响。 首先,理解Try-Catch的工作原理对于评估其性能至关重要。在...

    try_catch效率

    然而,一个常见的疑问是:`try-catch`是否会显著降低程序的执行效率?为了回答这个问题,我们需要深入理解`try-catch`的工作原理,并通过实际的性能测试来观察其对系统效率的影响。 首先,`try-catch`的基本工作...

    Try Catch对效能的影响测试

    这个测试是针对`Try...Catch`块对程序性能影响的一个研究,旨在理解在代码中使用异常处理时可能产生的性能开销。 异常处理是软件开发中的关键组成部分,它允许程序在遇到错误或异常情况时,仍能够优雅地执行,而...

    Java 的异常处理.pdf

    这表明,异常处理确实会对程序性能产生影响,尤其是在递归或深度调用的场景下。 在实际开发中,应该根据具体情况选择合适的异常处理策略。对于可以预见的异常,应尽可能在代码层面避免它们发生(防御性编程)。如果...

    杂谈try-catch-finally异常处理

    相关阅读:再谈异常处理try catch finally 1. 前言 最近这段时间正开发一个店铺管理系统,这个项目定位于给中小型店铺使用的软件系统。简单的说,它处理商品的进货,销售,退货等功能。软件虽小,五脏俱全,里面...

    再谈异常处理try catch finally

    在C#中,`try`块用于包含可能会抛出异常的代码,`catch`块用于捕获和处理这些异常,而`finally`块则确保无论是否发生异常,都会执行一段代码,通常用于资源清理。 在例一中,代码试图保存一个实体对象并使用`...

    Try-with-resources-Cwiczenie

    5. **性能与内存消耗**:可能会提及try-with-resources的性能优势,因为资源关闭是在finally块之前完成的,减少了额外的开销,并且可以避免因异常导致的资源未能及时关闭而造成的内存泄漏。 6. **并发考虑**:如果...

    java 自定义异常(基础)(csdn)————程序.pdf

    Java 自定义异常(基础) Java 中的自定义异常是一种特殊的异常类型,由用户自己定义和抛出,而不是由Java语言系统自动监测到的异常...但是,需要合理地使用自定义异常,避免过于频繁地抛出异常,从而影响程序的性能。

    C#-程序设计教程第7章.ppt

    - 如果没有合适的`catch`块处理异常,异常会被传递到调用栈上层,直到找到能处理它的代码,否则程序会终止,并显示未处理异常的错误信息。 **7.1.6 throw** - `throw`语句用于生成异常,可以是已存在的异常对象,...

    客户端--服务器聊天程序

    5. **错误处理**:在编程过程中,必须考虑网络异常、数据解析错误等可能发生的异常情况,并用try-catch语句进行捕获和处理,以确保程序的健壮性。 6. **文档和说明**:实验中提到有详细的使用和开发说明,这通常...

    高仿滴滴公交-查公交小程序源码.zip

    8. **性能优化**:小程序需要考虑加载速度和用户体验,源码可能会包含一些优化技巧,如懒加载、代码分割、资源预加载等。 总的来说,这个压缩包提供了一个实际的小程序开发案例,对于想要提升微信小程序开发技能的...

    C++中try throw catch异常处理的用法示例

    * 异常处理可能会影响程序的性能。 在实际应用中,C++异常处理机制可以用于处理各种异常情况,例如: * 文件读写异常 * 数学运算异常 * 内存分配异常 * 网络通讯异常 * 等等 通过使用C++异常处理机制,可以使得...

    通过Java代码技巧改善性能

    尤其是在循环体内使用try-catch语句时,对性能的影响将会成倍增加。以下是一个将try-catch应用于循环体内的示例代码: ```java @Test public void test11() { long start = System.currentTimeMillis(); int a = ...

    03-Java异常面试题.docx

    不要记录并抛出异常,包装异常时不要抛弃原始的异常,不要使用异常控制程序的流程,使用标准异常,异常会影响性能。 常见的 Java 异常面试题包括 Error 和 Exception 的区别是什么?运行时异常和一般异常(受检异常...

    Java异常面试题(2020最新版).pdf

    12. 异常会影响性能 13. 总结异常处理 Java异常面试题: 1. Error和Exception区别是什么? 2. 运行时异常和一般异常(受检异常)区别是什么? 3. JVM是如何处理异常的? 4. throw和throws的区别是什么? 5. final...

    C# 高性能服务器 - 端口-心跳高性能Socket服务器

    C#的`try-catch`块可以捕获并处理异常,同时,设计合理的重试和关闭连接的逻辑能帮助服务器快速恢复。 5. **缓冲区管理**:高效的数据读写离不开合理的缓冲区管理。C#的`NetworkStream`或`MemoryStream`可以用来...

    Java 基础(6-8) - 异常机制详解.pdf

    这个过程涉及到栈帧的回溯和异常匹配规则,可能会影响性能。因此,合理地使用异常处理可以避免不必要的性能损失。 总的来说,Java异常机制提供了一种优雅的错误处理方式,通过分层的异常类结构和明确的处理规则,...

    第38章至第48章--Java语言程序设计:进阶篇(原书第8版).rar )

    `try-catch-finally`块和`throws`关键字是其核心,理解何时抛出异常、如何捕获和处理异常对于编写健壮的代码至关重要。 6. 集合框架:Java集合框架包括接口(如`List`, `Set`, `Map`)和实现(如`ArrayList`, `...

    finally结构的注意点(一)

    7. **效率考虑**:虽然 `finally` 是确保代码执行的重要工具,但过度使用或设计不当的 `finally` 块可能会影响程序性能,因为它们增加了程序的复杂性和执行时间。 在实际开发中,理解并正确使用 `finally` 结构对于...

Global site tag (gtag.js) - Google Analytics