Runtime: Perf: Exceptions are much slower on .NET Core compared to .NET Framework

Created on 26 Jan 2019  路  8Comments  路  Source: dotnet/runtime

@realdotnetdave reported to us that exception performance is meaningfully different between .NET Core and .NET Framework. This article has his writeup.

| Method | Job | Runtime | Mean | Error | StdDev |
|------------------ |----- |-------- |----------:|----------:|----------:|
| ExceptionTryCatch | Clr | Clr | 6.630 us | 0.0244 us | 0.0217 us |
| ExceptionWithWith | Clr | Clr | 6.652 us | 0.1268 us | 0.1302 us |
| ExceptionTryCatch | Core | Core | 13.754 us | 0.1761 us | 0.1647 us |
| ExceptionWithWith | Core | Core | 13.963 us | 0.1087 us | 0.1017 us |

Code here for the benchmark.

area-ExceptionHandling-coreclr tenet-performance tracking-external-issue

All 8 comments

cc @janvorli @adityamandaleeka

@billwert do we have sufficient coverage of this in the perf repo?

@danmosemsft it鈥檚 on my list to check.

Note: behavior of this microbechmark depends on the machine configuration (OS version/hardware). On some configurations this code runs on CoreCLR 15-20% faster than on Desktop CLR.

@sergiy-k could you please share your recent finding on this?

The reason why exception handling is slower on .NET Core than on .NET Framework is Control Flow Guard.
.NET Core process/applicaiton has CFG enabled but the process created for .NET Framework does not:

dumpbin /headers netcoreapp2.2win-x86publishtestehwhen.exe
C140 DLL characteristics
Dynamic base
NX compatible
Control Flow Guard
Terminal Server Aware

The problem is that RtlpCallVectoredHandlers in ntdll.dll calls RtlpProtectReadOnlyHeap 4 times for each registered callout/handler. The RtlpProtectReadOnlyHeap/LdrProtectMrdataHeap function is a nop if CFG is disabled (like on .NET Framework) but if CFG is enabled, then it does lots of work including acquiring locks and querying/changing memory protection.

This performance regression is caused by a issue in the Control Flow Gurard (CFG) feature in certain Windows versions. It will be fixed in a future Windows update.

The .NET Core applications are opted into CFG by default. If this performance regression is a blocking problem for you, it can be worked around by disabling Control Flow Guard for the given application, e.g. run link /EDIT /GUARD:NO <exe name>.exe on the published .NET Core binary. Note that disabling CFG gives up defense in depth against security bugs that this feature provides.

Was this page helpful?
0 / 5 - 0 ratings