我们先来看看下面代码的执行效果:
下述代码中,依次扔出指定个数的异常,并显示这样做所花费的时间:
之前用的DateTime方式测试的数字不是很准确,下面做个修改,改成用System.Diagnostics.Stopwatch来测试所花费时间
class Program { static void Main(string[] args) { ThrowException(1); ThrowException(2); ThrowException(3); ThrowException(4); ThrowException(5); ThrowException(10); ThrowException(25); ThrowException(50); ThrowException(100); ThrowException(250); ThrowException(1000); Console.ReadLine(); } private static System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); static void ThrowException(int num) { Console.WriteLine(num); stopwatch.Reset(); stopwatch.Start(); for (int i = 0; i < num; i++) { try { throw new Exception("test Exception"); } catch (Exception) { } } stopwatch.Stop(); Console.WriteLine(stopwatch.Elapsed); Console.WriteLine("**************************************"); } }
下述执行值是在我公司台式机上的执行值: 我公司台式机配置(AMD 64 位3000+ CPU, 2GB RAM,Win2003 64 为操作系统)
1 00:00:00.0063479 ************************************** 2 00:00:00.0121209 ************************************** 3 00:00:00.0127166 ************************************** 4 00:00:00.0153518 ************************************** 5 00:00:00.0174371 ************************************** 10 00:00:00.0409867 ************************************** 25 00:00:00.0914862 ************************************** 50 00:00:00.1799064 ************************************** 100 00:00:00.3761265 ************************************** 250 00:00:00.9225065 ************************************** 1000 00:00:03.7062995 **************************************
由上可以看到,如果单位时间内产生异常数在某一个值范围内,异常的性能几乎可以忽略不计。而且花费时间几乎都一样。
但是,一旦超过这个阈值,则开始根据异常数翻倍需要处理的时间。
原因:
CLR 中的错误处理是借助结构化异常处理实现的。
引发托管异常之前,托管异常的开销非常小。
在 CLR 中,引发异常时,需要使用堆栈遍历为已引发的异常找到相应的异常处理程序。
堆栈遍历是一种开销较大的操作。
正如它的名称所表示的,异常应该用于异常或意外的情况,而不应该用于业务逻辑处理。
堆栈遍历的工作实际上就是从当前调用帧开始,反向遍历所有的堆栈帧,
处理能够处理的,跳过不能处理的,最终到栈顶结束遍历。
异常的工作原理,请参看有关结构化异常处理(Structured Exception Handling,SEH)的知识。
相关资料:
深入研究 Win32 结构化异常处理
http://vicchina.51.net/research/other/seh/crashcourse/intro.htm
http://vicchina.51.net/show_article.php?id=63
对于结构化异常处理(SEH)的进一步探索
http://vicchina.51.net/show_article.php?id=64
NT 中的异常帧结构和异常嵌套
http://vicchina.51.net/show_article.php?id=65
Under the hood: 从Win32 SEH到CLI异常处理模型
http://www.cnblogs.com/neoragex2002/archive/2006/04/16/376402.html
CLR 中代码访问安全检测实现原理
http://www.blogcn.com/user8/flier_lu/blog/3692778.html
A Crash Course on the Depths of Win32 Structured Exception Handling
http://www.microsoft.com/msj/0197/exception/exception.aspx
http://www.xfocus.net/articles/200503/785.html
http://www.bluedon.com/bluedo621/search/newsdisplay3.asp?id=1612&sort=3
由一个性能问题引出的.net概念
http://blog.youkuaiyun.com/lornshrimp/archive/2004/01/02/18878.aspx
编写高性能的托管应用程序:入门
http://www.microsoft.com/china/msdn/archives/library/dndotnet/html/highperfmanagedapps.asp#highperfmanagedapps_topic12
异常和性能
http://msdn2.microsoft.com/zh-CN/library/ms229009.aspx
异常设计准则
http://msdn2.microsoft.com/zh-CN/library/ms229014.aspx
异常性能计数器
http://msdn2.microsoft.com/zh-cn/library/kfhcywhs.aspx