当前位置:  开发笔记 > 编程语言 > 正文

.NET异常有多慢?

如何解决《.NET异常有多慢?》经验,为你挑选了4个好方法。

我不想讨论何时抛出异常而不抛出异常.我想解决一个简单的问题.99%的时间不抛出异常的论点围绕着它们缓慢而另一方声称(基准测试)速度不是问题.我读过很多关于一方或另一方的博客,文章和帖子.那是哪个呢?

答案中的一些链接:Skeet,Mariani,Brumme.



1> Jon Skeet..:

我处于"不慢"的一面 - 或者更准确地说"不够慢,不值得在正常使用中避免使用它们".我写了两篇关于此的短文 .有基准方面的批评,主要是"在现实生活中需要更多的堆栈,所以你要吹掉缓存等" - 但是使用错误代码在堆栈上工作也会打击缓存,所以我不认为这是一个特别好的论点.

只是为了说清楚 - 我不支持在不符合逻辑的情况下使用例外.例如,int.TryParse完全适合于转换用户的数据.它在读取机器生成的文件时是合适的,其中失败意味着"文件不是它的格式,我真的不想尝试处理这个,因为我不知道还有什么可能是错的. "

在"只有合理的情况"中使用例外情况时,我从未见过一个应用程序,其性能因异常而受到严重影响.基本上,除非你有明显的正确性问题,否则不应经常发生异常,如果你有明显的正确性问题,那么性能不是你面临的最大问题.


最后一句是福音.
@PaulLockwood:我想说如果你每*秒*有200多个例外,你就会滥用例外.如果它每秒发生200次,那显然不是"特殊"事件.请注意答案的最后一句:"基本上,除非你有明显的正确性问题,否则不应经常发生异常,如果你有明显的正确性问题,那么表现并不是你面临的最大问题."
是的,人们当然应该意识到与不恰当地使用异常相关的性能成本.我认为当它们*被正确使用时,这是一个非问题:)
@PaulLockwood:我的观点是,如果你每秒有200多个例外,那可能*已经*表明你在滥用例外.通常情况下,我并不感到惊讶,但这意味着性能方面不是我的首要考虑因素 - 滥用例外情况.一旦我删除了所有*不合适的*异常使用,我不会指望它们是性能的重要部分.
优秀的文章.
@DavidJeske:你错过了答案.显然抛出异常比返回正常值要慢得多.没有人在争论.问题是它们是否太慢*.如果您处于*适合*情况下抛出异常*和*会导致性能问题,那么您可能会遇到更大的问题 - 因为它表明您的系统存在大量*错误*.通常,问题是*真的*你在开始时不合适时使用异常.
不幸的是,人们被告知例外是免费的,将它们用于琐碎的"正确"功能,当事情出错时,应该按照你的说法使用它们 - 在'特殊'情况下
每秒200+的发生频率比人们想象的要高。我已经对许多公司进行了调整,实际上每个高流量站点都存在该问题。我看到一个拥有约30个四核服务器的站点曾经超过1000 / s!(DMZ中只有六个处理直接Web流量,但是仍然...)从经验来看,异常很慢,但是像Reflection一样,如果它很少发生,那么没什么大不了
令人不安的是,这个答案被投票得如此之高。.NET中的异常(与返回值进行比较时)非常慢。我的基准测试表明,它们比返回值慢1400倍。(见下文)

2> gbjbaanb..:

从实施它们的人那里得到了明确的答案 - 克里斯布鲁姆.他写了一篇关于这个主题的优秀博客文章(警告 - 很长)(警告2 - 写得非常好,如果你是技术人员,你会把它读到最后,然后不得不在下班后弥补你的工作时间:) )

执行摘要:它们很慢.它们被实现为Win32 SEH异常,因此有些甚至会传递0 0 CPU边界!显然在现实世界中,你将做很多其他的工作,所以奇怪的例外根本不会被注意到,但是如果你将它们用于程序流程,除了你的应用程序被锤击.这是MS营销机器给我们带来伤害的另一个例子.我记得有一个微软告诉我们他们如何产生绝对零开销,这是完全的tosh.

克里斯给出了一个相关的引用:

事实上,CLR内部甚至在引擎的非托管部分使用异常.但是,有一个严重的长期性能问题,例外情况,这必须考虑到您的决定.



3> Cory Foy..:

我不知道人们说什么,只有当他们被抛出时他们说他们很慢.

编辑:如果没有抛出异常,那么这意味着你正在做新的异常()或类似的东西.否则异常将导致线程被挂起,并且堆栈将被移动.在较小的情况下这可能是好的,但在高流量的网站中,依赖异常作为工作流或执行路径机制肯定会导致性能问题.例外情况本身并不错,对表达特殊情况很有用

.NET应用程序中的异常工作流使用第一次和第二次机会异常.对于所有异常,即使您正在捕获并处理它们,仍然会创建异常对象,并且框架仍然必须遍历堆栈以查找处理程序.如果你抓住并重新抛出当然需要更长的时间 - 你将获得第一次机会异常,抓住它,重新抛出它,造成另一个第一次机会异常,然后找不到处理程序,然后导致第二次机会例外.

例外也是堆上的对象 - 因此,如果您抛出大量异常,那么就会导致性能和内存问题.

此外,根据ACE团队撰写的"性能测试Microsoft .NET Web应用程序"副本:

"异常处理很昂贵.当CLR通过调用堆栈递归搜索正确的异常处理程序时,所涉及的线程的执行被暂停,当找到它时,异常处理程序和一些finally块必须都有机会执行在进行常规处理之前."

我在该领域的经验表明,减少异常有助于提高绩效.当然,在性能测试时还要考虑其他一些因素 - 例如,如果您的磁盘I/O被拍摄,或者您的查询是在几秒钟内,那么这应该是您的重点.但是,查找和删除异常应该是该策略的重要组成部分.


科里,我认为"只有当他们被抛出时才会缓慢"这一点是你不必担心性能,因为仅存在catch/finally块.即这些本身不会导致性能损失,只会发生实际的异常实例.
我知道 - 我是MSFT高级团队的一员.:)让我们说,很多 - 在我们看到的一些极端情况下,每秒数千.没有什么比连接现场调试器和只读你能读的异常更好的了.Ex很慢 - 所以连接到DB,所以你在有意义的时候这样做.

4> Ash..:

我理解的论点并不是说抛出异常本身就很慢.相反,它是关于使用throw/catch构造作为控制正常应用程序逻辑的第一类方法,而不是更传统的条件构造.

通常在正常的应用程序逻辑中,您执行循环,其中相同的操作重复数千/数百万次.在这种情况下,通过一些非常简单的分析(参见秒表类),您可以自己看到抛出异常而不是说简单的if语句可能会变得非常慢.

事实上,我曾经读到微软的.NET团队将.NET 2.0中的TryXXXXX方法引入许多基本FCL类型,因为客户抱怨他们的应用程序性能太慢.

事实证明,在许多情况下,这是因为客户在循环中尝试对值进行类型转换,并且每次尝试都失败了.抛出转换异常,然后由异常处理程序捕获,然后吞并异常并继续循环.

Microsoft现在建议在这种情况下应特别使用TryXXX方法以避免此类可能的性能问题.

我可能错了,但听起来你不确定你所读到的"基准"的真实性.简单的解决方案:亲自尝试一下.

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有