Try-Catch真的会影响程序性能吗

转载 2013年12月02日 22:18:53

转自:   http://www.cnblogs.com/isline/archive/2010/04/22/1717837.html  

   很多帖子都分析过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”吧。

try-catch影响性能吗?

try-catch会影响性能吗? try-catch放在循环块里面比放在外面程序运行会慢吗? 看到论坛上有人对try-catch对性能的影响存在疑问,比如: http://www.itey...
  • zdnlp
  • zdnlp
  • 2015年04月21日 20:57
  • 1216

制约程序性能的几大常见因素

计算机程序的性能准寻着木桶原理----木桶能装水的最大体积
  • shenlei19911210
  • shenlei19911210
  • 2014年09月29日 20:03
  • 817

你真的会php吗?

今天来讨论一道php代码审计的题,这是一道实验吧的题,链接: http://ctf5.shiyanbar.com/web/PHP/index.php 。 首先我们点开链接,并且查看源代码, 发...
  • JBlock
  • JBlock
  • 2017年12月07日 20:31
  • 757

程序性能优化之 内存分配影响

本篇不是介绍内存相关知识,如内存分配,布局等, 只是在程序优化性能时,结合案例跟大家分享,期间遇到情况,将知识点,做梳理,便于后续归类和记录,技术水平有限,如果有什么问题,及时给予指正。       ...
  • bingmeng2012
  • bingmeng2012
  • 2017年04月28日 14:37
  • 106

软件性能的影响因素

软件系统的性能表现受到很多因素的影响,主要因素包括硬件设施、网络环境、操作系统、中间件、应用程序、并发用户数、系统数据量等。 软件系统中影响性能的因素有很多,以WEB信息系统为例,会影响整体访问性能...
  • Tongdingsidong
  • Tongdingsidong
  • 2017年07月06日 17:34
  • 160

真的会读书吗?

不到1块钱买来的李笑来老师的读书经验 作者:乔向阳 链接:https://zhuanlan.zhihu.com/p/22540468 来源:知乎 著作权归作者所有。商业转载请联系作者获得授...
  • ww2041
  • ww2041
  • 2016年09月22日 09:32
  • 107

包装类的性能真的差么?

最近项目有一个问题。导出数据到excel的时候经常抛出heap space内存溢出异常。经过确认,是用户频繁点击导出按钮导致。 但是我很好奇这些数据到底占用了多少空间。我们的程序逻辑大概是这样的:从数...
  • winnerwxc
  • winnerwxc
  • 2016年07月18日 11:00
  • 308

影响网络应用程序性能的因素

随着网络的发展,越来越多的应用程序需要依赖于网络,所以网络的性能直接影响到我们应用程序的性能。那么都有那些因素影响到网络程序的性能来?我们以Windows平台上的应用程序来分析,首先将影响因素分为两个...
  • windcsn
  • windcsn
  • 2005年07月20日 10:40
  • 2557

cache line 对程序性能的影响

http://igoro.com/archive/gallery-of-processor-cache-effects/
  • pngfiwang
  • pngfiwang
  • 2016年01月10日 20:57
  • 208

细思极恐-你真的会写java吗?

细思极恐-你真的会写java吗? 导语 自2013年毕业后,今年已经是我工作的第4个年头了,总在做java相关的工作,终于有时间坐下来,写一篇关于java写法的一篇文章,来探讨一下如果你真的是一个...
  • sinat_32366329
  • sinat_32366329
  • 2017年03月12日 15:18
  • 901
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Try-Catch真的会影响程序性能吗
举报原因:
原因补充:

(最多只允许输入30个字)