The Performance of Exceptional Things

Following up from my previous blog post, I’ve had some cracking feedback from a number of people both for and against the use of exceptions – it’s one of those areas (as so many are in coding) that really does seem to have its own holy war.

On one side, those that are against the use of exceptions for ‘program flow’ (though I suspect if I looked at use cases in detail, I probably would be too) and see exceptions more for exceptional circumstances.  The approach favoured by this group tends to be in returning state and programming defensively to avoid exceptions wherever possible.

I totally agree with that final statement – if I have a method ‘IsLoggedIn’ and the user isn’t, then a simple ‘false’ will do and I’ll program defensively in that method to ensure that simple things like NullReferenceExceptions etc. aren’t thrown.

The other group like seem to like the concept of Business Exceptions as a means of handling logic, though (like me) they all wondered about the performance of that approach.

My Use Case

In the example code I put together for the last post, I used the business process of logging in the customer as a use case.  I could have equally used the concept of payments into the site, though obviously a far more significant use case that would have had me writing demo code long after it made sense to do so!

In my exceptions (User Not Found, Password Mismatch, Account in various ‘no play’ states), I’ve just done an analysis of yesterdays traffic to our site (which is hitting approx 1.8-2million unique visitors per month), and we have the following errors (all day):

  • User Not Found – 1842
  • Password Mismatch – 1125
  • Account Self Excluded / Account Cooling Off / Account Disabled / Account Closed – 240

So basically, 3207 things that in our new software will throw exceptions throughout a 24hr period, or 134 per hour, or 2.3 per minute.

Obviously there are payment type errors to take into account, which I suspect will be busier, lets say up to 20-30 exceptions per minute (tops).

So just how heavy are these exceptions?

I’ve updated the hosted code I used in the previous post, and have created two approaches to getting user data – one via models, one via exceptions.  The main web navigation at the top of the page will allow you to test with exceptions or test with models.

I basically setup a test to fail login (User Not Found), and iterated through it 10,000 times, and the code is in there both for exceptions and testing returning models.

I then iterated over those 10,000 tests 10 times each.

Yup, I know this isn’t really as indicative a test as it demonstrates best possible outcomes (the exceptions being repeatedly called will obviously do some form of optimisation that is beyond me!), but it’s helpful as one measure when the core thing people mention is performance.

And yup, there *is* a performance hit when throwing exceptions – no denying it.

But when you look at the code, failing login and returning a model (single run of 10,000 fails) averages out at 289.6ms, whereas with Exceptions, the same 10,000 iteration comes out at 624.1ms.  That makes a single exception (my maths is shite, so happy to be corrected on this) take 0.034ms more to throw.

Oops! Ignore the ticks figures below – I actually (stupidly) divided Ticks by 10,000 rather than Stopwatch.Frequency, so they’ll be slightly out – the milliseconds figures reflect reality though.

  Measured in Ticks     Measured in Milliseconds  
Run Exceptions Models   Exceptions Models
1 2150098 1009757   628 290
2 2165310 1018790   624 287
3 2144660 1018190   622 288
4 2136548 1012047   623 293
5 2139677 1009204   621 289
6 2154162 1011982   627 289
7 2146923 1019645   623 290
8 2167315 1026824   623 289
9 2148493 1011428   626 291
10 2156894 1008608   624 290
Avg Ticks 2151008 1014648      
           
Avg Ms 215.1008 101.4648   624.1 289.6
           
Ms per iteration 0.02151008 0.010146   0.06241 0.02896
           
Cost Increase for Ex   0.011364     0.03345

Where are the real stats?

Well, this is where my naivety kicks in and I really must defer to clever people.  Odd to think I’m a senior dev when I can’t effectively dig any further into it than where I’m at currently, but I’ve found a few cracking posts that really help me see that I’m happy with the approach we’re taking with regards to Business Exceptions (I promise to post when this goes live to let you know if the performance hit took our site down though!).

Blog 1 – Rico Mariani

Rico is (as they say) the man, and he really knows his stuff – he certainly sits on the ‘don’t do this’ side of the holy war, and has good reasons.  He highlights that iterative testing like the above is certainly a ‘best case’ and wouldn’t demonstrate typical usage.

http://blogs.msdn.com/ricom/archive/2006/09/25/771142.aspx

Blog 2 – Jon Skeet

I like this one, it kinda supports our approach! lol.  In particular, a great quote from him:

“If you ever get to the point where exceptions are significantly hurting your performance, you have problems in terms of your use of exceptions beyond just the performance.”

http://yoda.arachsys.com/csharp/exceptions2.html

Blog 3 – Krzysztof Cwalina

This is *exactly* how I see our approach to exceptions, and I agree with Jon Skeet, I couldn’t have put it even 10% as good as Krzysztof has.  His bullet point list of Do’s and Don’ts is brilliant.

http://blogs.msdn.com/kcwalina/archive/2005/03/16/396787.aspx

Code Project Post – Vagif Abilov

I thought this one interesting as he’s gone into far more detail in terms of the tests than I have, and his conclusions are interesting.

http://www.codeproject.com/KB/exception/ExceptionPerformance.aspx

Blog 4 – Eric Lippert

Not one so much on performance, as a ‘don’t throw exceptions when you don’t need to’, and there are often ways around throwing exceptions if you code ‘well’.

http://blogs.msdn.com/ericlippert/archive/2008/09/10/vexing-exceptions.aspx

Blog 5 – Krzysztof Cwalina

Another that I’ve linked to just for the quote which very much reflects my thinking:

“One of the biggest misconceptions about exceptions is that they are for “exceptional conditions.” The reality is that they are for communicating error conditions. From a framework design perspective, there is no such thing as an “exceptional condition”. Whether a condition is exceptional or not depends on the context of usage, — but reusable libraries rarely know how they will be used. For example, OutOfMemoryException might be exceptional for a simple data entry application; it’s not so exceptional for applications doing their own memory management (e.g. SQL server). In other words, one man’s exceptional condition is another man’s chronic condition.”

http://blogs.msdn.com/kcwalina/archive/2008/07/17/ExceptionalError.aspx

Exception Management Guidance – Multiple authors

Some good feedback re: exceptions in this post.

http://www.guidanceshare.com/wiki/.NET_2.0_Performance_Guidelines_-_Exception_Management

Closing

I’ve updated the code on Google Code at: http://code.google.com/p/business-exception-example/ to cover both Exceptions and Models if anyone wants a looksy.

Again though, really interested in hearing thoughts on this.  I think from the performance testing I’ve done and the posts I’ve read, I’m happy with our approach, but I’m equally happy for someone to come along and shout NOOOOOOO! and tell me why I’m an idiot :)

Over to you guys, and thanks for all the feedback thus far!

Business Exceptions in c# (as I understand them!)

Thought I’d best caveat the post as this really is just a collection of thoughts from a number of very clever people, and I’ve come to wonder over the past few days (since #dddscot) whether this is a good way to handle business exceptions or not.

My approach has been born out of a cracking talk by Jeffrey Richter at DevWeek this year (see the summary post elsewhere in my blog) where he talked about exception within your software and (as @plip did at dddscot this year) about embracing them.  He talked about exceptions in the following way though:

  1. Exceptions are not just for exceptional circumstances
  2. They are there as a means of saying ‘something hasn’t worked as expected, deal with it’
  3. They should be thrown when they can reliably be managed (be that logging or something else)
  4. They should be useful/meaningful

In my other post, I used the example of ProcessPayment as a method, and the various things that could go wrong during that method, but I thought I’d bring together a simple app that demonstrates how we are using exceptions currently.

The reason for this post

There was a lot of discussion after #dddscot about how folks handle this sort of thing, and really, there were some very clever people commenting!  It’s kinda made me nervous about the approach we’re taking, you all know the crack:

Dev1: “And that new method works even if the input is X, Y, and A?”

Dev2: “It did until you asked me, but now I’m going to have to test it all again!”

Ahhh, self doubt, you have to love it :)

Though I digress – basically, I would love to get some feedback from the community on this one.

Business information – what are the options?

Ok, if we take a simple method call, something like:

ProcessLogin(username, password)

How can we find out if that method fails for whatever reason?  If it does fail, why does it fail?  Was the username wrong?, is their account disabled?, did the password not match up?  This is a relatively straight forward method which is why I’ve chosen it for the demo, though there are any number of things that can go wrong with it.

Option 1 – returning an enum or something that can identify the type of error

So the method signature could be:

public ProcessLoginResult ProcessLogin(string username, string password) {
	// stuff
}

public enum ProcessLoginResult {
	Success,
	Fail_UsernameMismatch,
	Fail_PasswordMismatch,
	Fail_AccountDisabled,
	Fail_AccountCoolingOff,
	Fail_AccountSelfExcluded,
	Fail_AccountClosed
}

You may feel like that’s a lot of fail states, but these are what I work with in my current environment so they have to be included.

Obviously then we have something from the calling code like:

var result = ProcessLogin(username, password);

if (result != ProcessLoginResult.Success) {
	switch(result) {
		case ProcessLoginResult.UsernameMismatch:
		case ProcessLoginResult.PasswordMismatch:
			ModelState.AddModelError("General", "We have been unable to verify your details, etc. etc.");
			break;
		case ProcessLoginresult.[errorstate1]
			return RedirectToAction("ErrorState1", "ErrorPages");
		case ... [for each extra error state]
	}
}

There are obvious pro’s to this approach from my point of view – one is that we’re not throwing exceptions!  People talk a lot about the performance overhead in actually throwing new exceptions – there’s generally a sucking in of teeth as they do this.  I personally have no idea how “expensive” they are to raise, and it’s certainly something I’ll have to look into.

The difficulty here for me though is two-fold:

  1. If I want the richness of business information to return from my methods on failure, I need to come up with (almost) an enum per method to define the states that it can return with?
  2. If I have a different method (e.g. GetUserById(userId)) my only option is to setup the method signature with the user as an out param or pass it down by reference.

Option 2 – Business Exceptions

And this is the approach I’ve taken, though again – feedback very much appreciated!  Each of the possible fail states becomes a potential exception.  So the ProcessLogin method becomes:

///

/// Processes the login.  Steps are:
///  - Check the existence of the user
///  - Check the password matches (yup, we'd be hashing them here, no need for the demo)
///  - Check the account status
/// 

///
The username.
///
The password.
/// 
public MyCompanyUser ProcessLogin(string username, string password)
{
	MyCompanyUser user;

	try
	{
		user = dal.GetUserByUsername(username);
	}
	catch (MyCompanyUserNotFoundException)
	{
		//TODO: LOGGING
		throw; // but then pass the exception up to the UI layer as it is most easily able to deal with it from a user perspective
	}

	if (user.Password != password)
	{
		//TODO: LOGGING
		MyCompanyUserWrongPasswordException ex = new MyCompanyUserWrongPasswordException("Password doesn't match");
		ex.Data.Add("Username", username);
		// potentially if you had an MD5 or something here you could add the hashed password to the data collection too

		throw ex;
	}

	switch(user.AccountStatus)
	{
		case AccountStatus.SelfExcluded:
		{
			//TODO: LOGGING
			MyCompanyUserSelfExcludedException ex = new MyCompanyUserSelfExcludedException("User self excluded");
			ex.Data.Add("Username", username);
			throw ex;
 		}
		case AccountStatus.CoolingOff:
		{
			//TODO: LOGGING
			MyCompanyUserCoolingOffException ex = new MyCompanyUserCoolingOffException("User cooling off");
			ex.Data.Add("Username", username);
			throw ex;
		}
		case AccountStatus.Disabled:
		{
			//TODO: LOGGING
			MyCompanyUserAccountDisabledException ex = new MyCompanyUserAccountDisabledException("Account disabled");
			ex.Data.Add("Username", username);
			throw ex;
		}
		case AccountStatus.Closed:
		{
			//TODO: LOGGING
			MyCompanyUserAccountClosedException ex = new MyCompanyUserAccountClosedException("Account closed");
			ex.Data.Add("Username", username);
			throw ex;
		}
	}
	return user;
}

obviously with this in place I can either Log at this level or log at the UI layer (I don’t have a strong feel architecturally either way).

The process login method call at the UI layer then becomes a little more convoluted:

try
{
	MyCompanyUser user = service.ProcessLogin(model.Username, model.Password);

	return RedirectToAction("LoggedIn", "Home");
}
catch (MyCompanyUserSelfExcludedException)
{
	return RedirectToAction("SelfExcluded", "ErrorPages");
}
catch (MyCompanyUserCoolingOffException)
{
	return RedirectToAction("CoolingOff", "ErrorPages");
}
catch (MyCompanyUserAccountDisabledException)
{
	return RedirectToAction("AccountDisabled", "ErrorPages");
}
catch (MyCompanyUserAccountClosedException)
{
	return RedirectToAction("AccountClosed", "ErrorPages");
}
catch (MyCompanyUserException)
{
	// if we're this far, it's either UserNotFoundException or WrongPasswordException, but we'll catch the base type (UserException)
	// we can log them specifically, handle them specifically, etc. though here we don't care which one it is, we'll handle them the same
	ModelState.AddModelError("General", "We have been unable to match your details with a valid login.  (friendly helpful stuff here).");
}

I don’t know why I find this a more elegant solution though – it certainly doesn’t generate any less code! There is very much a need for good documentation in this one (each method call documenting what types of exceptions can be thrown).

Want to see more?

I’ve put together a test VS2010 project using MVC2 and separate projects for the exception definitions and one for the models/services/dal stuff.

It’s rudimentary, but our core solution as Unity in there as an IoC container, it has interface based Services and Repositories, it has unit tests etc. and it just wasn’t viable (or commercially acceptable) to make any of that available, so I’ve distilled it down to the basics in the solution.

What I’d love now is feedback – how do people feel about this approach (Business Exception led) as opposed to the other?  What other approaches are available?  Is it bad to use exceptions in this way (and I’m fine if the answer is ‘ffs tez, stop this now!’ so long as there’s a good reason behind it!)

The code is available on google code at: http://code.google.com/p/business-exception-example/

and I’ve only created a trunk (subversion) at present at: http://code.google.com/p/business-exception-example/source/browse/#svn/trunk

Feedback pleeeeeez!

Developer Developer Developer Scotland, or summer arrives early in Glasgow!

Who let the sun out?

What a stunning day we were all faced with for #dddscot this year – the drive up from Newcastle (albeit starting at an ungodly hour) was actually fun – great scenery on the way, I’d forgotten what it was like to get out of a built up area – plenty more trips out needed over the summer methinks.  I had high expectations of the event after attending #ddd8 earlier in the year and being overwhelmed by the content there, and the day didn’t disappoint.

Onto the talks I managed to get to:

HTML 5: The Language of the Cloud?

Craig Nicol – @craignicol

A good start to the day, and pertinent for my current role (we’re investigating what HTML5 can do to help us with alternate platform delivery, certainly with a focus on the mobile market).  Craig’s talk was animated (in both senses of the word!), and it was useful to see just where the ‘standards’ were at.  Safe to say at present, and Craig mentioned it a few times during this talk, that if you want to target HTML5 then you really do need to pick your target browser (or generate more work usually and target browserS), as the standards are still significantly in flux.  There is a lot of help out there, and those people creating mashups really are helping in showing which browsers support which elements.

I particularly liked the look of the XForms (forms 2.0) stuff – being able to define something as an ‘email’ field, or a ‘telephone’ or ‘uri’ I think adds significant context to the proceedings and will deliver (for the users) a far richer experience.

As with a lot of emerging technologies though, I certainly think it’s far too early for reliable deployment in all but very controlled environments – even if you implement progressive enhancement well.  Something to follow for sure though.

Overall a very well presented talk, a minimal smattering of the expected ‘this worked 10mins ago!’, but this is HTML5+bits, so to be expected.

Exception Driven Development

Phil Whinstanley – @plip

plip at his usual exuberant self with this talk on exceptions, and it was a useful additional session to one I’d seen at DevWeek earlier in the year given by Jeffrey Richter.  The initial message was ‘exceptions happen’ – we have to learn how to live with them, what to do when they happen, which ones we should fix (and yup, I’m one of those people that hates warnings, so I suspect I’ll have to fix all of them!), which ones we should prioritise – how we make sure we’re aware of them, that sort of thing.

Two very useful additions to my current understanding – one was ‘Exception.Data’ which is essentially a dictionary of your own terms.  At present we’re throwing our own exceptions within our business software (more on that later), but .Data will give us far more information about what parameters were at play when the exception happened – utterly brilliant, and terrifying that I didn’t know about this!

Another was the use of window.onerror in javascript – ensure that you http post (or whatever other mechanism works best for you) when your scripts don’t work – there’s nothing worse than your javascript borking and not being able to repeat it, so make sure you report upon these too.

Some key snippets (some common sense, some not) such as never redirect to an aspx page on a site error (thar be dragons and potential infinite loops), go do static html instead.

plip’s acronym at the end of the session made me chuckle, I shant repeat it, but it had an odd way of sticking in the consciousness ;)

The only thing I thought lacking in this talk (and it’s no real criticism of plip) was the concept that was covered in that talk earlier in the year at DevWeek.  The idea that Exceptions are *not* for exceptional circumstances, they’re there as a means of controlling program flow, of reporting when something didn’t work as expected, and of giving more effective information.

So for example, if I had a method called ‘ProcessLogin(username, password)’ and one of the first checks was ‘does this username exist in the DB’, if it doesn’t, throw new UserNotFoundException.

Of course, if plip had gone down the custom exceptions and business defined exceptions, the talk could comfortably lasted two to three times longer, so I feel the devweek talk and plip’s complemented each other well.

Cracking talk though plip – really did get a lot out of this one, and I think this was the most useful session of the day for me.

A Guided Tour of Silverlight 4

Mike Taulty – @mtaulty

A reminder from Mike that I really need to spend some time looking into Silverlight 4.  I focus very heavily on web development and web technologies, and although I have little interest in desktop development, SL4 I think has a lot of interest in terms of as an intranet based tool with rich GUI.  Of course, I may be better going down the WPF route with that, but there’s something about the versatility of SL4 that appeals.

Cracking talk from Mike as per – always good to see one of the UK evangelists wax lyrical about their current focus, and this was no exception.

What ASP.NET (MVC) Developers can learn from Rails

Paul Cowan – not sure on twitter

I have to prefix this talk by saying that I thought Paul’s presentation style was great, and much as he maligned his irish accent, he was cracking to listen to.

That said – rails… what a bag of shite! lol.  I suspect I may get a number of replies to this, but what I like about MVC2 is that I can focus on architecture and the important stuff, and ‘get the job done’ without too many interruptions.  Ok, I have to add views myself, and a ‘Customer’ entity doesn’t automatically get a controller/views/unit tests associated with it.  But I feel in complete control, and don’t feel constrained at all.

I spent too many years in a unix/perl/python environment, and I really do not miss the command line shite I had to go through to really add value to what I was doing in the programming language.

VS2010 + Resharper deliver a significant number of improvements in the ‘streamlining’ of application development, and I have none of the hassle that came about as part of that rails demo (no matter how much it delivered with just a simple command line).

So I really do apologise to Paul – his presentation was great, but it only reinforced for me that the love affair I’m having with MVC2 at present is well grounded.  God, I sound like such a fanboy!

Real World MVC Architectures

Ian Cooper – @icooper

A few teething troubles at the start (don’t you just hate it when a backup brings your system to its knees), but overall a good presentation – I’d seen Ian’s talk at #ddd8 (prior to really solidly working with MVC), and I thought I’d re-attend this again after spending 2months solidly working with MVC2.  It has certainly reinforced what I’m doing is ‘right’ or at least appears to be good practice.  I’m still sceptical about the overhead that CQRS delivers when implemented in its purest sense, though the principles (don’t muddy up your queries with commands, and vice versa) is a one that obviously all should follow.

Ian had a bit of a mare with his demo code, though more to my benefit as I managed to nab some swag for being ‘that geek’ in the front row pointing it out – yay for swag!

The Close

Colin Mackay and the rest of the guys then spent some time covering the day, handing out significant swag (yay, I won a resharper (or if I can wing it as I have one) a dotTrace license!), and we had the obligatory Wrox Lollipop shot taken.

All in all, it was a cracking day, and well worth that early drive up from Newcastle – I think events like this work so well – getting a room or rooms full of enthusiastic devs, who all just want to be better at their art, and being presented to by people who’ve spend some time working on that art.  There’s nothing finer in the geek world.

Thanks to all organisers and sponsors – great fun was had by all :)

Unity 2.0 – Just in the nick of time

We’re just re-architecting our site currently and a big part of that is test first (I daren’t call it test driven!) development.  It’s an MVC2 project, with distinct business and data access layers. I’m loving MVC2, model binding, and the power I’m getting from making my domain models richer.

Obviously one of the biggies in unit testing is the use of Inversion of Control via an IoC container (older list) so that you can reliably pass around interfaces rather than implementations, the aim being to improve the testability of it all, and allowing mocking up of dependencies in order to test just certain areas of the functionality.

I’d investigated a few IoC containers:

  • CastleWindsor – I just personally found this too much like hard work in terms of the thinking side of things – I didn’t like the syntax, which must be an utterly personal thing as there’s not a big difference between that an Unity.
  • StructureMap – this one felt more like voodoo, though worked well – was definitely a good second choice.
  • Unity (v1.2) – I liked the config on this one, and I liked the way of specifying which constructor to use in a multi-constructor dependency.  What I didn’t realise was that it didn’t out of the box seem to support the ‘PerWebRequest’ type lifestyle on dependencies (though I managed to roll my own without too much difficulty).

I’d hasten to add the above are my findings, and may not be fully representative of someone with a clue playing with this!  I may easily have missed elements in the initial plays.

Unity 2.0 (which is available as part of Enterprise Library 5) comes with a ‘PerResolveLifetimeManager’ out of the box now, which does exactly what it says on the tin – during a running instance (in this case, a web request) the first time it resolves it’ll new up an instance for the app, and during that instance it’ll use that one, until the next instance (page load).

So we have:

container.RegisterType<iwebsessionmanager , WebSessionManager>(new PerResolveLifetimeManager(), new InjectionConstructor(typeof(IUserService), typeof(ISessionManager)));

instead of the default TransientLifetimeManager.

There are other lifetime managers available with Unity 2.0 (HierarchicalifetimeManager being the other new one), and obviously you still have ExternallyControlledLifetimeManager should you need it.

All in all, very happy that we went down the Unity route when we did, and those updates in 2.0 have proven to come just when we needed them.

p.s. I’ll add links to the correct MSDN sections as soon as they’re available – the documentation only seems available for 1.2 at present.