try catch对程序性能的影响

大家看到这样的标题也许会在想,try catch肯定会影响性能的,但是其实并没有很直接的证据表明trycatch会影响系统的性能,尤其是在托管的环境下,今天就用实际的代码来证明下在不同情况下,代码运行的时间指标。

.NET中的异常捕获以及处理的机制都是try catch finally块来完成的,作用分别是异常的检测 捕获以及处理。

每个类都会跟一个异常表(exception table) 每一个try catch都会在这张表里面添加记录,每一个记录都有四个值:try catch的开始地址 结束地址 异常处理的起始位 异常类名称。当代码抛出异常的时候,首先会拿着抛出的位置到异常表里面按顺序去查找是由有可以合适的catch(例如查看位置是不是处于任何一个的开始和结束位置之间),如果有,则跑到异常的开始位置开始处理,如果没有在原地return,并且copy异常的引用,返回给父调用方,继续查找父的异常表,以此类推。如果无异常发生,只需要遍历finlly项,那几乎跟正常的无区别,如果发生了异常,只不过多了一个遍历exception table然后在遍历finlly项。记住:trycatch引起的反应只是监控与触发,这一部分的消耗微乎其微

如下实例:

public static void TryCatch()
        {
            try
            {
                Convert.ToInt32("Try");
            }
            catch (FormatException ex1)
            {
                Console.WriteLine(ex1.Message);
            }
            catch (NullReferenceException ex2)
            {
                Console.WriteLine(ex2.Message);
            }
            finally
            {
                Console.WriteLine("Finally");
            }
        }
IL代码:
<pre class="csharp" name="code">.method public hidebysig static void  TryCatch() cil managed
{
  // 代码大小       69 (0x45)
  .maxstack  1
  .locals init ([0] class [mscorlib]System.FormatException ex1,
           [1] class [mscorlib]System.NullReferenceException ex2)
  IL_0000:  nop
  .try
  {
    .try
    {
      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_0032
    }  // end .try
    catch [mscorlib]System.FormatException 
    {
      IL_0010:  stloc.0
      IL_0011:  nop
      IL_0012:  ldloc.0
      IL_0013:  callvirt   instance string [mscorlib]System.Exception::get_Message()
      IL_0018:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_001d:  nop
      IL_001e:  nop
      IL_001f:  leave.s    IL_0032
    }  // end handler
    catch [mscorlib]System.NullReferenceException 
    {
      IL_0021:  stloc.1
      IL_0022:  nop
      IL_0023:  ldloc.1
      IL_0024:  callvirt   instance string [mscorlib]System.Exception::get_Message()
      IL_0029:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_002e:  nop
      IL_002f:  nop
      IL_0030:  leave.s    IL_0032
    }  // end handler
    IL_0032:  nop
    IL_0033:  leave.s    IL_0043
  }  // end .try
  finally
  {
    IL_0035:  nop
    IL_0036:  ldstr      "Finally"
    IL_003b:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0040:  nop
    IL_0041:  nop
    IL_0042:  endfinally
  }  // end handler
  IL_0043:  nop
  IL_0044:  ret
} // end of method Program::TryCatch


 

然后我们比较一下正常的情况下与加了try catch的之间的区别:

static void Main(string[] args)
        {
            //Stopwatch stop1 = new Stopwatch();

            //stop1.Start();
            //for (int i = 0; i < NUM_TESTS; i++)
            //{
            //    tryInLoop();
            //}
            //stop1.Stop();
            //Console.WriteLine(stop1.ElapsedMilliseconds);


            Stopwatch stop2 = new Stopwatch();
            stop2.Start();
            for (int i = 0; i < NUM_TESTS; i++)
            {
                TryOutLoop();
            }
            stop2.Stop();
            Console.WriteLine(stop2.ElapsedMilliseconds);

            Stopwatch stop3 = new Stopwatch();
            stop3.Start();
            for (int i = 0; i < NUM_TESTS; i++)
            {
                InLoop();
            }
            stop3.Stop();
            Console.WriteLine(stop3.ElapsedMilliseconds);

            Console.ReadLine();
        }

        //public static int tryInLoop()
        //{
        //    int count = 0;
        //    for (int i = 0; i < ITERATIONS; i++)
        //    {
        //        try
        //        {
        //            count += 1;
        //        }
        //        catch (NotFiniteNumberException ex)
        //        {
        //            return 0;
        //        }
        //    }
        //    return count;
        //}

        public static int InLoop()
        {
            int count = 0;
            for (int i = 0; i < ITERATIONS; i++)
            {
                    count += 1;
            }
            return count;
        }


        public static int TryOutLoop()
        {
            int count = 0;

            try
            {
                for (int i = 0; i < ITERATIONS; i++)
                {
                    count+=1;
                }

                return count;
            }
            catch (NotFiniteNumberException ex)
            { return 0; }
        }

对比的结果:


由此可见基本上是没有差别的,另外有些人对trycatch在for里面与外面的性能也有怀疑,认为放在里面的性能会差些,真的么?取消注释上面的代码,再看看结果


我们发现性能的影响基本上可以忽略不计的,除非你是对性能有苛刻的要求。针对是在循环里面进行trycatch还是外面,主要是一个代码习惯的问题,还有就是你是否有需要for的循环执行完毕的选择,并未有很大的影响
谢谢

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值