try catch对程序性能的影响
2016-02-02 14:48
351 查看
大家看到这样的标题也许会在想,try catch肯定会影响性能的,但是其实并没有很直接的证据表明trycatch会影响系统的性能,尤其是在托管的环境下,今天就用实际的代码来证明下在不同情况下,代码运行的时间指标。
.NET中的异常捕获以及处理的机制都是try catch finally块来完成的,作用分别是异常的检测 捕获以及处理。
每个类都会跟一个异常表(exception table) 每一个try catch都会在这张表里面添加记录,每一个记录都有四个值:try catch的开始地址 结束地址 异常处理的起始位 异常类名称。当代码抛出异常的时候,首先会拿着抛出的位置到异常表里面按顺序去查找是由有可以合适的catch(例如查看位置是不是处于任何一个的开始和结束位置之间),如果有,则跑到异常的开始位置开始处理,如果没有在原地return,并且copy异常的引用,返回给父调用方,继续查找父的异常表,以此类推。如果无异常发生,只需要遍历finlly项,那几乎跟正常的无区别,如果发生了异常,只不过多了一个遍历exception
table然后在遍历finlly项。记住:trycatch引起的反应只是监控与触发,这一部分的消耗微乎其微
如下实例:
然后我们比较一下正常的情况下与加了try catch的之间的区别:
对比的结果:
由此可见基本上是没有差别的,另外有些人对trycatch在for里面与外面的性能也有怀疑,认为放在里面的性能会差些,真的么?取消注释上面的代码,再看看结果
我们发现性能的影响基本上可以忽略不计的,除非你是对性能有苛刻的要求。针对是在循环里面进行trycatch还是外面,主要是一个代码习惯的问题,还有就是你是否有需要for的循环执行完毕的选择,并未有很大的影响
谢谢
.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的循环执行完毕的选择,并未有很大的影响
谢谢
相关文章推荐
- 如何在 Linux 中安装微软的 .NET Core SDK
- C#.NET获取拨号连接的宽带连接方法
- C#.Net ArrayList的使用方法
- PowerShell中使用.NET将程序集加入全局程序集缓存
- .net(c#)中的new关键字详细介绍
- 由vbs sort引发.NET Framework之间的关系说明
- C#难点逐个击破(6):C#数据类型与.net framework数据类型
- .NET中的async和await关键字使用及Task异步调用实例
- .Net中的json操作类用法分析
- .net实现序列化与反序列化实例解析
- .NET中的Timer类型用法详解
- 关于.net(C#)中的跨进程访问的问题
- .NET实现父窗体关闭而不影响子窗体的方法
- 基于.Net中的数字与日期格式化规则助记词的使用详解
- .NET微信公众号开发之公众号消息处理
- .Net下的签名与混淆图文分析
- .NET 扩展实现代码
- .net实现网站用户登录认证
- .NET实现定时发送邮件代码(两种方式)
- .net实现文件读写的几种常用方法