DCSIMG
Exceptions are common enemies of Web Apps performance - LINQED.NET

LINQED.NET

This blog is about .NET and related technologies
By Vlad Azarkhin

Exceptions are common enemies of Web Apps performance

(Update: Thanks to Avi Pinto for pointing out at a stupid mistake regarding catching exceptions in every method. What I meant was that it is a bad practice catching exceptions in every method. Don’t catch exceptions if you have nothing to do with them)

Yes, exceptions are one of most common sources of performance issues of any .NET application, and especially of ASP.NET Web Applications. Without going into details, every thrown exception, either handled or not, introduces a serious penalty on the code execution time.

Consider the following two simplistic functions:

private static int Divide(int a, int b)
{
  if (b == 0) return int.MaxValue;
  return a / b;
}

private static int DivideEx(int a, int b)
{
  try
  {
      return a / b;
  }
  catch (DivideByZeroException ex)
  {
      return int.MaxValue;
  }
}

The first one checks the input, and returns the maximum value of integer in case of invalid denominator. The second one, relies on the user input, and handles the exception. Unfortunately, in my practice I’ve seen much more of the second type of function. Now let’s see what this does to the execution performance.

I’m gong to use the following method to benchmark the performance of the above functions:

private static long ProfileDivideFunc(Func<int, int, int> func)
{
  Random rnd = new Random(DateTime.Now.Millisecond);
  Stopwatch sw = new Stopwatch();
  sw.Start();
  for (int i = 0; i < 10000; i++)
  {
      func(rnd.Next(0, i), 0);
  }
  sw.Stop();
  return sw.ElapsedMilliseconds;            
}

Nothing fancy here. The only “interesting” thing is that the method accepts a delegate and invokes it. Inside the method, I’m just running the tested function 10,000 times, passing a random integer as nominator, and zero as denominator. Practically, I’m measuring the performance penalty of throwing and catching 10,000 exceptions.

The results are pretty much as expected. On my D-Core/4G/Win7 x64 laptop, the first function test returns 0ms, whereas the second function (the one with exceptions), takes 422ms to complete.

It sounds like nothing, however, consider what happens, in ASP.NET app, when 500 or 1,000 concurrent requests are being handled. Also take into consideration the fact that usually we don’t catch exceptions in every method (catching exception in every method is a very bad practice), so it bubbles all the way to some top-level-exception-catching-mechanism. In addition, it has to be logged, which also takes some CPU cycles.

I’ve recently seen a web app, that thrown and logged 3 exceptions on each and every request. Needless to mention how the performance was improved after eliminating the sources for those exceptions.

So here are couple of recommendations:

  • Never, and I repeat, never, throw exceptions. Use response error codes if you need to indicate and error.
  • Verify user input. Don’t handle exceptions following bad input.
  • Try eliminating usage of functions that throw exceptions in case of invalid input, like Parse(). Use TryParse() instead.
  • Watch for exceptions, log them and eliminate their sources ASAP.
  • There is nothing worst than unhandled exceptions in ASP.NET application. Catch everything in some top-level mechanism, like Application_Error of global.asax, or connect to AppDomain.CurrentDomain.UnhandledException event to catch and log them all.

The most important this is: remember, Exceptions are EXCEPTIONS from the normal, so they should be treated accordingly. They are not NORMAL at runtime.

Have fun.

Want to know why you should use IIS7 ? Come to see me at Developers Academy 4.

clip_image001

Comments

Exceptions are common enemies of Web Apps performance - LINQED.NET Zero Me said:

Pingback from  Exceptions are common enemies of Web Apps performance - LINQED.NET Zero Me

# March 12, 2010 2:30 AM

ידיד said:

ידידי להגיד שאסור ולא מומלץ להשתמש ב exception ב web applications הוא טעות מיסודה. אין ספק שיש overhead כלשהו בשימוש ב exceptions אך הוא קטן וזניח.

ככלל הכלל להשתמש ב exceptions לתפוס אותם ולטפל מאוד ולא משנה באיזו מערכת מדובר הוא מאוד פשוט:

אם יש לך מה לעשות במידע של ה execption שנתפס תתפוס אותו ( ולמשל תכתוב ללוג)

אם אין לך מה לעשות איתו תן לו להזרק במעלה ה stack.

# March 14, 2010 1:05 PM

linqed said:

יש כאן בעיה מאוד רצינית של שילוב אנגלית ועברית, אז אכתוב את זה באנגלית:

You are perfectly right - the correct concept is, if you have nothing to with the exception, don't catch it, and let it bubble to the top.

However, one should understand a difference between error and exception.

I rarely accept the design that throws exceptions to indicate errors. Exceptions are exceptional to the application flow, thus the performance penalty.

Disregarding the performance issue, from my point of view, "throw new Exception(...)", is pretty similar to the GOTO statement. You don't use goto any more, so why would you throw an exception?

And believe me, exceptions seriously affect the performance of multi-user web applications. Only yesterday I've seen the remarkable 400% drop in web app performance because of thrown exceptions.

Happy coding and catching :)

# March 14, 2010 1:42 PM

ידיד said:

This is not what i said.

You wrote never use exceptions in a web application.

I not suggesting that sending and throwing exceptions is a good paractice but you can use then and its very much o.k

# March 15, 2010 10:09 AM

linqed said:

Yadid, can you identify yourself?

Are you attending the Dev Academy? If so, find me. I'd love to discuss this.

Regards,

Vlad

# March 15, 2010 11:29 AM

The annoyimous said:

I am the annonymous critiziser :-)

Just kidding. What are you lecturing about in the dev academy?

# March 15, 2010 1:03 PM

linqed said:

I'm doing the IIS 7 Demo Session:

www.microsoft.com/.../Dev_Sessions.aspx

You're mostly welcomed.

# March 15, 2010 1:33 PM

LINQED.NET said:

I’ve just spent two days and a night between them on the client site, trying to solve a severe performance

# March 16, 2010 4:53 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: