Ste*_*idi 0 .net optimization jit exception-handling try-catch
我一直在考虑嵌套的try/catch语句,并开始考虑JIT可以在哪些条件下执行编译IL的优化或简化.
为了说明,请考虑以下功能等效的异常处理程序表示.
// Nested try/catch
try
{
try
{
try
{
foo();
}
catch(ExceptionTypeA) { }
}
catch(ExceptionTypeB) { }
}
catch(ExceptionTypeC) { }
// Linear try/catch
try
{
foo();
}
catch(ExceptionTypeA) { }
catch(ExceptionTypeB) { }
catch(ExceptionTypeC) { }
Run Code Online (Sandbox Code Playgroud)
假设在嵌套的try语句的堆栈帧中没有额外的变量引用或函数调用,JIT可以断定堆栈帧可能会折叠为线性示例吗?
现在下面的例子怎么样?
void Try<TException>(Action action)
{
try
{
action();
}
catch (TException) { }
}
void Main()
{
Try<ExceptionC>(Try<ExceptionB>(Try<ExceptionA>(foo)));
}
Run Code Online (Sandbox Code Playgroud)
我认为JIT没有任何方法可以内联委托调用,所以这个例子不能简化为前一个.然而,在foo()投掷的情况下ExceptionC,与线性示例相比,此解决方案的性能是否更差?我怀疑从委托调用中拆除堆栈帧需要额外的成本,即使帧中包含的额外数据很少.
值得注意的是,在第一种情况下,当你在catch区块内什么也不做时,它们只是在功能上是等价的.否则,考虑一下:
try
{
foo();
}
catch (IOException)
{
throw new ArgumentException(); // Bubbles up to caller
}
catch (ArgumentException)
{
Console.WriteLine("Caught");
}
Run Code Online (Sandbox Code Playgroud)
VS
try
{
try
{
foo();
}
catch (IOException)
{
throw new ArgumentException(); // Caught by other handler
}
}
catch (ArgumentException)
{
Console.WriteLine("Caught");
}
Run Code Online (Sandbox Code Playgroud)
现在在这种情况下,差异是显而易见的,但如果catch块调用一些任意方法,JIT如何知道可能抛出什么?最好要小心.
这让我们可以选择JIT对空捕获块执行优化 - 这种做法首先是强烈劝阻的.我不希望JIT花时间尝试检测错误的代码并使其运行得更快 - 如果确实首先存在任何性能差异.