.net - 空的 catch 和 throw block 会做什么?

标签 .net performance exception

我知道下面的 catch and throw block 是多余的,我很好奇它能造成什么样的破坏?

编译器可以在 Release模式下优化它吗?或者它无论如何都会捕获异常并重新抛出它?如果是后一种情况,会造成什么样的性能损失?

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

最佳答案

优化

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

采用以下测试应用程序:

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 查看输出二进制文件等级。我们看到 CallsThrow 中的 try/catch 仍然存在于我们的 Release 二进制文件中:

.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,Release 版本显示出 23.42% 的实质性改进。

关于.net - 空的 catch 和 throw block 会做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19920063/

相关文章:

c# - 异常处理

ASP.NET 自定义错误页面 - Server.GetLastError() 为 null

c# - 通过反射获取公共(public)静态字段的值

c# - DateTime 通过内部刻度进行比较?

android - 如何仅在 Ubuntu 上安装 Android Studio 命令行工具

Android xml vs java 布局性能

.net - 如何调试打包在 .NET 程序集中的 .NET 代码(作为单独软件运行)

c# - 为什么 StreamReader 返回字符串而不是字节数组

performance - 在 Perl 中高效处理所有可能的二维数组组合

java - 如何检测 Java 中全局抛出异常的时间?