为什么尝试块很贵?

Est*_*aya 51 .net coding-style

我听说过你应该避免尝试使用catch块的建议,因为它们很贵.

我的问题是关于.NET平台:为什么尝试块很昂贵?

回复摘要:

在这个问题上显然有两个阵营:那些说试试块是昂贵的,那些说"可能只是一点点".

那些说try块很贵的人通常会提到解除调用堆栈的"高成本".就个人而言,我不相信该辩解-阅读有关的异常处理程序如何存储后,专门在这里.

Jon Skeet坐在"可能只是一点点"的阵营中,写了两篇关于异常和性能的文章,你可以在这里找到.

有一篇文章我觉得非常有趣:它谈到了try块的"其他"性能影响(不一定是内存或cpu消耗).Peter Ritchie提到他发现try块中的代码没有被优化,因为它本来是编译器的.你可以在这里阅读他的发现.

最后,有一篇博客文章介绍了在CLR中实现异常的人的问题.在这里看一下Chris Brumme的文章.

Bob*_*ing 20

块本身并不昂贵,而且它甚至不会捕获异常,本身就是昂贵的,它是运行时展开调用堆栈,直到找到可以处理异常的堆栈帧.抛出异常是非常轻量级的,但是如果运行时必须向上走6个堆栈帧(即深度为6个方法调用)以找到适当的异常处理程序,可能会执行finally块,因此可能会看到明显的时间量.

  • 此外,扫描调试数据以解析打印堆栈跟踪的方法名称和行号会增加很多开销. (4认同)

Sco*_*man 12

您不应该避免使用try/catch块,因为这通常意味着您没有正确处理可能发生的异常.结构化异常处理(SEH)仅在实际发生异常时才很昂贵,因为运行时必须遍历调用堆栈以查找catch处理程序,执行该处理程序(并且可能有多个),然后执行finally块,然后返回控制回到正确位置的代码.

异常不是用于控制程序逻辑,而是用于指示错误条件.

关于例外的最大误解之一是它们用于"特殊条件".现实情况是它们用于传达错误条件.从框架设计的角度来看,没有"特殊条件"这样的东西.条件是否异常取决于使用的上下文,但可重用的库很少知道如何使用它们.例如,对于简单的数据输入应用程序,OutOfMemoryException可能是例外; 对于进行自己的内存管理的应用程序(例如SQL服务器)来说,这并不是那么特别.换句话说,一个人的特殊情况是另一个男人的慢性病. [http://blogs.msdn.com/kcwalina/archive/2008/07/17/ExceptionalError.aspx]


Mic*_*tta 5

我认为人们真的高估了抛出异常的性能成本.是的,有一个性能损失,但它相对较小.

我运行了以下测试,抛出并捕获了一百万例外.我的英特尔酷睿2双核处理器需要大约20秒,2.8 GHz.这是每秒约50K例外.如果你投入的只是其中的一小部分,那么你就会遇到一些架构问题.

这是我的代码:

using System;
using System.Diagnostics;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < 1000000; i++)
            {
                try
                {
                    throw new Exception();
                }
                catch {}
            }
            Console.WriteLine(sw.ElapsedMilliseconds);
            Console.Read();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这有点误导.几乎总是,抛出异常不会在同一个方法中处理,而是在到达catch {}之前冒出几个级别.那么你会看到真实世界的性能影响,这种影响在很大程度上是可变的. (3认同)

Ant*_*ony 5

尝试块根本不贵.除非抛出异常,否则很少或不产生任何费用.如果抛出异常,这是一种特殊情况,你不再关心性能了.如果您的程序需要0.001秒或1.0秒才能倒下,这是否重要?不,不是的.重要的是报告给您的信息有多好,以便您可以修复它并再次阻止它.