Recently, I submitted a tip to Red Gate for their “50 Ways to Avoid, Find and Fix ASP.NET Performance Issues” e-book. If you haven’t had a chance to download it, you should because it’s free.
My tip was called “Remove Unused View Engines”, and showed you how to disable the WebForms view engine from getting in the way of your Razor view engine. A lot of folks don’t realize that you can do this, and that this small performance tweak can save you a little bit of time in the long run.
Let’s discuss how ASP.NET MVC handles View Engines. I’m specifying MVC, because if you’re using WebForms you don’t have access to the Razor view engine.
Let’s imagine that a request comes into your web server for http://yourdomain.com/. I’m assuming you’re familiar with basic ASP.NET MVC routing, and understand that his request will be forwarded to your Home controller and Index action. The default action for Index is to render a View called Index.
This is where the process becomes interesting. ASP.NET MVC really has no idea where you’ve decided to put the Index view. It determines the view location but using a series of conventions that are built in.
Have you ever seen a screenshot like this?
ASP.NET MVC is being really nice to you by divulging the locations it’s searching for your view. What’s happening behind the scenes? Here’s how ASP.NET MVC interacts with the View Engines.
ASP.NET: What View Engines do I have loaded? I see WebFormsViewEngine and RazorViewEngine. Hey WebFormsViewEngine, are you able to render a view called Index that came from the Home controller?
WebFormsViewEngine: Let me check. Is there a file called Views/Home/Index.aspx? No. Is there a file called Views/Home/Index.ascx? No. Ok ok. Maybe there is an Index.aspx or Index.ascx in the Views/Shared directory? No. Sorry, ASP.NET, I don’t have a view to render.
ASP.NET: Hey RazorViewEngine! Can you render a view called Index that came from the Home controller?
RazorViewEngine: I’ll see what I can do. Is there a file called Views/Home/Index.cshtml? No. How about Index.vbhtml? Nothing. Ok, I’ll check in the Views/Shared directory too. Nothing I can do, ASP.NET.
ASP.NET: Thanks for checking. ERROR.
Excuse the dramatization, but it’s accurate of how the conversation works in ASP.NET. If you’re developing solely in Razor with MVC, you’re spending a decent amount of time per request to locate views that will never exist.
My tip was to remove the WebForms view engine in your Global.asax file.
Tada! You’re done with WebForms. Beware, don’t do this if you’re actually using the WebForms view engine. You’ll get an error screen.
It might be interesting to visualize this with Glimpse. Here is a website that uses both view engines by default:
Compare it to a screen shot of the same site using only the Razor view engine.
If we have two view engines, we see that ASP.NET is doing two lookups per view engine in the worst case scenario. First, ASP.NET checks it’s cache for the view engine (more on that in a moment). If it’s not found, it attempts to render it with the view engine.
In the scenario, we have a view that contains a partial view. This means there are a total of 8 lookups before ASP.NET finally finds what it’s looking for.
In the second screen shot, we only see 4 lookups. If you have a site with multiple partial views, you’ll see faster lookups by reducing the number of locations ASP.NET needs to go.
How much does this actually save you? Here is the dirty truth, if you’re running in release mode, you’ll gain almost nothing from this. MVC is really good about caching its lookup results when running in release (note the lookups that Glimpse told us about). Take the conversation between ASP.NET and the view engines, and add in an additional comment where ASP.NET makes a note of how to render the view.
In Debug mode, this will pay dividends over and over again. In fact, depending on how you stage your benchmarking tests, removing an unused view engine can give you a huge boost in performance. We’re talking about milliseconds though. For a second request, a couple milliseconds doesn’t seem like much. It’s when you start to add up thousands of requests, the performance gains will really start to shine through.
Closing up, this is a good tip and should be a first step in any new ASP.NET MVC application where you know WebForms will not be used. Your development experience will be fantastic. When you’re ready to deploy, make sure you flip the appropriate Debug-to-Release switches, and enjoy even better performance.
Kevin Griffin is the owner of Griffin Consulting, Inc and is the Chief Technology Officer for Winsitter, Inc. He’s an ASP.NET MVP and an ASPInsider. He blogs on occasion over at http://www.kevgriffin.com and tweets all the time at @1kevgriff. If you’re looking for a great developer for your next project, give Kevin a call.