# Monday, February 21, 2011
« Mono 2.10 Released | Main | CLR Type Names »
Exception Performance Part 3

This is the final part of three part series on exception performance that started in 2008. Previous parts are:
Exception Performance Part 1
Exception Performance Part 2

Let's introduce a slight variation of ExceptionPerf1 where we throw 10000 exceptions instead of 100000 and throw the exception from a method, instead of directly in the loop.

using System;
using System.Diagnostics;

class ExceptionPerf5 {
  static void Main() {
    var sw = Stopwatch.StartNew();
    for (int i = 0; i < 10000; i++) {
      try {
      } catch { }

  private static void Foo() {
    throw new Exception();

When this is compiled with the standard Debug configuration in Visual Studio 2010 it yields the following performance numbers (times in milliseconds) when run either with Ctrl-F5 (i.e. no debugger attached) or F5 (debugger attached):

  HotSpot 1.6 .NET 2.0 .NET 4.0
  x86 x86 x64 x86 x64
Ctrl-F5 25 286 413 292 305
F5   16950 16134 45223 114790

For comparison, the table also includes the time it takes to run the equivalent code in HotSpot 1.6 Client VM on x86.

As we saw in the previous two articles on exception performance, .NET is significantly slower in handling exceptions, so that is not surprising. However, what is surprising is how much the overhead is of simply having the debugger attached.

Another depressing thing to note is that things have gotten much worse with .NET 4.0.

Unfortunately, many developers have the habit of always running their code in the debugger, so when they first try code IKVM.NET compiled code from within Visual Studio they often get a very bad impression of the performance, simply because the debugger sucks.

I considered filing a connect bug for this, but you know they'll just close it as By Design. I guess the CLR is only a Common Language Runtime, if you language doesn't use exceptions for control flow.

Monday, February 21, 2011 9:46:12 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [5]
Monday, February 21, 2011 10:10:58 AM (W. Europe Standard Time, UTC+01:00)
The debugging architecture of VS changed in 2010. I've found some of the details in this Connect entry:

Monday, February 21, 2011 1:57:39 PM (W. Europe Standard Time, UTC+01:00)
This really is "by design": it's a design issue in the .NET debugger API (ICorDbg).
Whenever an exception happens while a debugger is attached, the .NET runtime informs the debugger and stops the current thread. The debugger is informed using a cross-process COM call - not exactly the fastest beast in the world.
But wait - it gets worse. The debugger, once it has identified that it doesn't want to break on that exception, cannot simply call Go(). This is because callbacks from the debuggee arrive on multiple threads (MTA), but calling into the .NET runtime is allowed only on a single thread (a slightly weird variant of STA).
So what the debugger needs to do is to enqueue the "Go()" command, and wake up the STA thread. That one can then call Go() and tell the .NET runtime to continue.
This means throwing an exception takes no less than three context switches until execution can continue.
Daniel Grunwald
Monday, February 21, 2011 6:31:18 PM (W. Europe Standard Time, UTC+01:00)
I am sure that's the matter of tradeoff.

Optimizing debugging interfaces for 10K exceptions is unlikely to help any noticeable number of people. Who cares, basically?

On the other side, improving JIT, building postmortem and mixed mode support is what would make an impact.

Oracle might have chosen to build a better 10K machinegun exceptions support instead of proper generics or delegates or closures. I'd love to see anybody defending that position ;-)
Tuesday, February 22, 2011 11:31:05 PM (W. Europe Standard Time, UTC+01:00)
What about release mode handling of the exception.
All you compare now is the performance of Visual Studio vs IKVM which has no value.
There is nothing about the CLR in your test.
Compile in Release and run with Ctrl+F5.

Monday, March 14, 2011 3:32:54 PM (W. Europe Standard Time, UTC+01:00)
"I guess the CLR is only a Common Language Runtime, if you language doesn't use exceptions for control flow."

No need to guess! :)

See the CLI Annotated Standard. In my (very old) edition, Annex D.4 says "Do not use exceptions for normal flow of control" and "Do design classes such that in the normal course of use there will never be an exception thrown".
Comments are closed.