C# 深度剖析try catch finally及其性能影响

  关于try-catch-finally的使用本文不做探讨,详见try-catch参考
  本文想真正剖析的是在代码中使用try-catch-finally块对于性能的影响。很多程序员认为:只要没有异常抛出,try就没有额外的性能开销。为此,我们先来看微软官方给出的解释:

Throw Fewer Exceptions

Throwing exceptions can be very expensive, so make sure that you don’t throw a lot of them. Use Perfmon to see how many exceptions your application is throwing. It may surprise you to find that certain areas of your application throw more exceptions than you expected. For better granularity, you can also check the exception number programmatically by using Performance Counters.MSDN

   上述第一句便讲明了抛出异常开销非常大(相对而言),所以不要过多的在程序中使用它们。如果不能理解这句话,请尝试运行以下代码:
  

public static void Main(string[] args){
  int j = 0;
  for(int i = 0; i < 10000; i++){
    try{   
      j = i;
      throw new System.Exception();
    } catch {}
  }
  System.Console.Write(j);
  return;   
}

  上面代码片中有一个循环,它执行10000次try-catch块,抛出10000个异常,在每次循环检测到异常后,CLR会自上而下搜索catch块的代码,并通过异常过滤器筛选对应的异常,如果没有找到,那么CLR将沿着调用堆栈,向更高层搜索匹配的异常,如果已到堆栈顶部依然没有找到对应的异常,就会抛出未处理的异常了,这时catch块中的代码并不会被执行。所以距离try最近的catch块将最先被遍历到。
  在stackoverflow上有关于实例更为详细的代码,详情参阅:try-catch块性能开销实例
  在基于X86架构的.NET2.0中,即时(just-in-time)编译器禁用最优化会影响CIL语言对于受保护块的读写操作,由此可见,即使没有异常抛出,try-catch块也会有一定的性能开销,看下面的例子:
  

    int count = 1;
    SomeMethod();
    count++;
    SomeOtherMethod();
    count++;
    Console.WriteLine(count);

  X86即时编译器会将其优化为以下形式:

    SomeMethod();
    SomeOtherMethod();
    Console.WriteLine(3);

  最终结果虽然一致,但其副作用却不相同(这种影响一般只能在调试器中观察到)。
通过如下方式把代码放在try语句中:

    int count = 1;
    try
    {
        SomeMethod();
        count++;
        SomeOtherMethod();
        count++;
    }
    finally
    {
        Console.WriteLine(count);
    }

  变量count的值初始为1,并在SomeMethod()方法调用后变为2,在SomeOtherMethod()方法调用后变为3,最终的输出结果也会是3,在其过程中有两次增量操作是额外的开销浪费。
以上几个例子告诉我们写try-catch语句的时候一定要注意以下几点:

  1. 尽量给CLR一个明确的异常信息,不要使用Exception去过滤异常
  2. 不要轻易将try-catch写在循环中
  3. try尽量少的代码,如果有必要可以使用多个catch块,并且将最有可能抛出的异常类型,书写在距离try最近的位置
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值