捕获异常时是否真的有性能损失?

3 language-agnostic exception-handling exception

我问了一个关于异常的问题,我对那些说投掷很慢的人非常恼火.我过去问例外幕后是如何工作的,我知道在正常的代码路径有没有额外的指令(作为接受的答案说的),但我不完全相信投掷比较贵然后检查返回值.考虑以下:

{
    int ret = func();
    if (ret == 1)
        return;
    if (ret == 2)
        return;
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

VS

{
    try{
        func();
        doSomething();
    }
    catch (SpecificException1 e)
    {
    }
    catch (SpecificException2 e)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

据我所知,除了ifs从正常的代码路径移出到异常路径和额外的跳转或两个到达异常代码路径之外没有区别.额外的一两跳不会听起来像是if在你的主要代码路径中减少了几个s.那些异常实际上是慢的吗?或者这是旧编译器的神话还是旧问题?

(我在谈论一般的异常.具体来说,编译语言中的异常,如C++和D;虽然C#也在我的脑海中.)

Aar*_*ron 8

好的 - 我只是进行了一些测试,以确保异常实际上更慢.简介:在我的机器上,每次迭代调用w/return是30个循环.每次迭代抛出w/catch为20370个循环.

所以回答这个问题 - 是的 - 抛出异常很慢.

这是测试代码:

#include <stdio.h>
#include <intrin.h>

int Test1()
{
    throw 1;
//  return 1;
}


int main(int argc, char*argv[])
{
    int result = 0;
    __int64 time = 0xFFFFFFFF;
    for(int i=0; i<10000; i++)
    {
        __int64 start = __rdtsc();
        try
        {
            result += Test1();
        }
        catch(int x)
        {
            result += x;
        }
        __int64 end = __rdtsc();
        if(time > end - start)
            time = end - start;
    }

    printf("%d\n", result);
    printf("time: %I64d\n", time);
}
Run Code Online (Sandbox Code Playgroud)

另一种尝试/捕获由op编写

try
{
        if(Test1()!=0)
                result++;
}
catch(int x)
{
        result++;
Run Code Online (Sandbox Code Playgroud)


Cha*_*ana 5

我不确切知道它有多慢,但是抛出已经存在的异常(比如它是由CLR创建的)并没有太慢,因为你已经引发了构造异常的命中....我相信这是一个异常的构造,创造了大部分的附加性能命中...想想看,它必须创建一个堆栈跟踪,(包括读取调试符号以添加行号和东西)并可能捆绑内部异常等

实际抛出异常只会添加额外的代码来遍历堆栈以找到适当的catch子句(如果存在)或将控制转移到CLR未处理的异常处理程序......对于非常深的堆栈,这部分可能很昂贵,但是如果例如,catch块就在你扔进去的同一个方法的底部,那么它会相对便宜.