什么会空捕和扔块呢?

时间:2013-11-12 02:59:29

标签: .net performance exception

我知道以下catch and throw块是多余的,我很好奇它可以造成什么样的伤害?

编译器可以在发布模式下优化它吗?或者它只会抓住异常并重新抛出它?如果是后一种情况,会导致什么样的性能损失?

try
{
  //...
}
catch {
  throw;
}

1 个答案:

答案 0 :(得分:7)

优化

即使在发布版本中,编译器也不会对此进行优化。

参加以下测试申请:

public class Program {
    public static void Main(string[] args) {
        try {
            CallsThrow();
        }
        catch(Exception ex) {
            Console.WriteLine("Main() caught exception: " + ex.Message);
        }
        Console.Read();
    }

    private static void CallsThrow() {
        try {
            Throw();
        }
        catch {
            throw;
        }
    }

    private static void Throw() {
        throw new Exception("Here's my exception.");
    }
}

使用ILSpy我们可以查看IL级别的输出二进制文件。我们发现try中的catch / CallsThrow仍在我们的发布二进制文件中:

.method private hidebysig static 
    void CallsThrow () cil managed 
{
    // Method begins at RVA 0x2094
    // Code size 11 (0xb)
    .maxstack 1

    .try
    {
        IL_0000: call void JunkCSharpConsole.Program::Throw()
        IL_0005: leave.s IL_000a
    } // end .try
    catch [mscorlib]System.Object
    {
        IL_0007: pop
        IL_0008: rethrow
    } // end handler

    IL_000a: ret
} // end of method Program::CallsThrow

基准

<强>代码:

public class Program
{
    public static void Main(string[] args) {
        const int N = 100000000;
#if DEBUG
        const string mode = "Debug";
#else
        const string mode = "Release";
#endif

        Console.WriteLine("Testing {0} iterations in {1} mode:", N, mode);

        // Attempt to JIT / cache
        CallsThrowWithTryCatch(false);
        CallsThrowWithoutTryCatch(false);

        // Test with try/catch+throw
        var s1 = Stopwatch.StartNew();
        for (int i = 0; i < N; i++ )
            CallsThrowWithTryCatch(false);
        s1.Stop();
        Console.WriteLine("  With try/catch: {0} ms", s1.ElapsedMilliseconds);

        // Test without try/catch+throw
        var s2 = Stopwatch.StartNew();
        for (int i = 0; i < N; i++)
            CallsThrowWithoutTryCatch(false);
        s2.Stop();
        Console.WriteLine("  Without try/catch: {0} ms", s2.ElapsedMilliseconds);

        var pct = (s1.ElapsedMilliseconds - s2.ElapsedMilliseconds) / (double)s1.ElapsedMilliseconds * 100.0;
        Console.WriteLine("No try/catch faster by {0:.02}%", pct);

        // Just show that it works
        try {
            CallsThrowWithTryCatch(true);
        }
        catch (Exception ex) {
            Console.WriteLine("Main() caught exception: " + ex.Message);
        }

        // Wait to exit
        Console.WriteLine("Press ENTER to exit.");
        Console.Read();
    }

    private static void CallsThrowWithTryCatch(bool doThrow) {
        try {
            Throw(doThrow);
        }
        catch {
            throw;
        }
    }

    private static void CallsThrowWithoutTryCatch(bool doThrow) {
        Throw(doThrow);
    }

    private static void Throw(bool doThrow) {
        if (doThrow)
            throw new Exception("Here's my exception.");
    }
}

<强>结果:

Testing 100000000 iterations in Debug mode:
  With try/catch: 1492 ms
  Without try/catch: 1474 ms
No try/catch faster by 1.22%
Main() caught exception: Here's my exception.
Press ENTER to exit.

Testing 100000000 iterations in Release mode:
  With try/catch: 598 ms
  Without try/catch: 458 ms
No try/catch faster by 23.42%
Main() caught exception: Here's my exception.
Press ENTER to exit.

我们可以看到,是的,即使空try / catch 也会导致性能损失。在Debug版本中,它并不那么重要,但是通过删除try / catch,版本构建显示了23.42%的显着提升。