Exceptions are expensive!

Hey! Don't we all use Exceptions in managed code to indicate the caller that something is wrong? That's a really bad habit! - "Hey maaaan, it's the 21st century, passing back HRESULTs is over!" - not yet, you'll see it: did you know that if your caller can systematically force your code to throw an exception (by passing wrong parameters, etc), your application could be DOSed down? It's just a matter of the amount of threads running on the defender's box and the power of the server your code running at. To demonstrate this thingy, I hammered together a small app:

The following is a function that can work in two different ways:

  1. Returning an exception, simulating a function that communicates back to its caller by throwing exceptions on deterministic inputs. MyOwnException is just a class inherited from the ApplicationException class
  2. Returning an integer number, simulating a function that works in an "old-fashioned" HRESULT-way 
 static int TesterMethod(bool throwException)
{
    if (throwException)
    {
        throw new MyOwnException();
    }
    else
    {
        return 1;
    }
}

(HRESULT is representing an alternative way of passing back the result of a function as a variable or pointer, it's not neccessarily should be the old-fashioned HRESULT, it could be a structure or class containing information about what happened)

... and here's the function that will drive this baby: it's simple: there's a stopwatch we use to measure time, and we call the function in both ways 1,000 times:

 static void Main(string[] args)
{
    Stopwatch stopWatch = Stopwatch.StartNew();
    
    // PHASE I: DOING THE EXCEPTION-TEST
    
    // Reset and start the stopwatch
    stopWatch.Reset();
    stopWatch.Start();
    
    // Call the function 1,000 times, an exception will be
    //  thrown at every call
    for (int i = 0; i < 1000; i++)
    {
        try
        {
            TesterMethod(true);
        }
        catch (MyOwnException)
        {
            // Do something to handle ...
        }
    }
    
    // Stop the watch and show the time elapsed
    stopWatch.Stop();
    Console.WriteLine("Exception: " + stopWatch.Elapsed);

    
    // PHASE II: DOING THE "HRESULT" TEST

    // Reset and start the stopwatch again
    stopWatch.Reset();
    stopWatch.Start();
    
    // Calling the function 1,000 times again, but now in
    //  the HRESULT-way
    int retVal = 0;
    for (int i = 0; i < 1000; i++)
    {
        retVal = TesterMethod(false);
    }
    
    // Stop the stopwatch and display the results
    stopWatch.Stop();
    Console.WriteLine("HRESULT " + stopWatch.Elapsed);

}

Surprise!

 Exception: 00:00:03.1247094<br>HRESULT:   00:00:00.0000287

I hope that you noticed the seconds part, not only the milliseconds part! After some time, I was rethinking the whole thing, because it seemed to be too much of a difference, then I found that I made a mistake when measuring the performance: I was running the code from the Visual Studio IDE, meaning that I was debugging the process, which slows down 1st chance exceptions, so a big part of this difference was due to the operating system informing the debugger about the 1st chance exceptions. Release compiled the project, ran it outside the debugger and got a much better performance for exceptions, but still a huge difference:

 Exception: 00:00:00.2039267<br>HRESULT:   00:00:00.0000058

This is all about performance and security. One can say that these are just milliseconds per one thousand cycles. That's true for one thread, but think about an ASP.net application or a service accepting huge amount of TCP connections, with 25 worker threads per processor. If there's a function inside that can be forced from outside to throw an exception, this could be a big performance impact on your service. So, think twice before throwing an exception.