-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exception try catch performance 10 times low than java #12892
Comments
Code:
|
See https://github.com/dotnet/coreclr/issues/22224#issuecomment-499657814 |
Tested on Virtual Machine Ubuntu 18.04.2 LTS
3405/237=14.367 |
Benchmarking in Java is hard to get right, more so than .NET. You should consider writing a JMH Benchmark to ensure that the timings are correct (BenchmarkDotNet was partly inspired by JMH, so the benchmark code will look similar). |
Times changed from 100,000 to 1000,000 on windows the result is:
30401ms/726=41.87 So mybe it's not need to get accurate time, since more than 40 times 9.9 or 10.1, 39 or 41 are similar. To avoid java compiler optimize the code, a counter to sum exception times added. and the result is:
1000000 times exception throw and catched in fact. public void Test() {
Instant start = Instant.now();
System.out.println(ExceptionTest(1000_000));
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println(duration.toMillis());
}
private long ExceptionTest(long times) {
long result = 0;
for (int i = 0; i < times; i++) {
try {
throw new Exception();
} catch (Exception ex) {
//Ignore
result++;
}
}
return result;
} |
Just upping a counter doesn't mean it doesn't get optimized away, you would need to throw from a different method and block that method from being inlined, except that i couldn't find a hint to block the JVM from inlining a method public void Test() {
Instant start = Instant.now();
System.out.println(ExceptionTest(1000_000));
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println(duration.toMillis());
}
private long ExceptionTest(long times) {
long result = 0;
for (int i = 0; i < times; i++) {
try {
Throw();
} catch (Exception ex) {
}
}
return result;
}
//@NoInlining <-- would need something like this
private void Throw() throws Exception {
throw new Exception();
} |
Exception performance in .NET is known to be slow. I think this is becoming more and more of a problem because:
I have worked on multiple applications where exceptions became a performance issue. The code was not bad. Fairly frequent errors were in the nature of the application. Also, when the Visual Studio Debugger is attached exceptions again become 10-100x slower. |
@mattwarren exception handling slow is known, however compare to java .net exception handling 10 or 40 times slow is surprise, two platform both with GC different so much, so there must be some problem in .NET |
I've tried to profile the C# EH example above on Windows. 24% of the time is spent in RaiseException, 17% in RtlLookupFunctionEntry, 10% in RtlVirtualUnwind, 6.4% in EtwEventWrite, 5.5% in EtwEventWriteTransfer and 2.7% in RtlUnwindEx. All the percentages are exclusive. It sums up to 65.6%. All of these functions are in the Windows ntdll.dll, so .NET Core cannot do much about this time. |
.NET Core can avoid this overhead by handling the exceptions internally, without involving the Windows OS exception handling. It is what CoreRT does. CoreRT runs the exception handling microbenchmarks like the one above number of times faster. There is nothing fundamental (except the huge amount of work involved) that prevents porting the same scheme to CoreCLR. |
It might be good to tackle this in .NET 6. I saw some of these stacks when I was debugging a performance run. It seems like there's some lock in the OS when exceptions get thrown. There were lots of concurrent sockets disconnecting at the same time and it resulting in high CPU. |
I'm the current maintainer of IKVM. I can vouch for this. :) |
A compare test did, result says: performance of try catch throw Exception in .Net is over 10 times slow than in Java.
Reproduce:
C# code
Java Code
Test Result:
2151/175=12.29
source code at https://github.com/chrishaly/DotNetVsJavaPerformanceTest
The text was updated successfully, but these errors were encountered: