Performance differences in the ASP.Net MVC View Engine when using two View Engines versus a single Composite View Engine.


While I was testing out my VirtualPathProvider implementation in the Opinionated Input Builders series I ran across an interesting performance difference which was quite surprising.  In fact even after looking at the source code to the MVC ViewEngineCollection it still seemed like this difference should not occur.  But it does and I am sure that we will get to the bottom of this. 

Don’t go jumping to any conclusions just yet about how this performs because the one common piece of functionality that these engines still rely on is a VirtualPathProvider that I implemented and I can honestly say I understand very little about how the VPP is used and how to ensure that it was implemented correctly to ensure maximum performance.

The first part of this graph (the green line) shows the requests / second that I can get through my MVC view when using two ViewEngines, the default view engine to handle all requests to the /Views/{controller} and /Views{Shared} . The second view engine Handles all requests to my virtual path /Views/InputBuilders/ .  At the 7:50 mark I changed the flag and recompiled the application.  You see a small dip while the application restarts with the new code in place.  Now the application uses a single view engine that handles all the views for the default locations and my extra virtual path.



Here is the part of my codebase that shows the difference between adding my ViewEngine to the collection and Clearing the Collection and adding the view engine with parameters to handle the additional view locations.



The source code for the project I am testing is located here: incase you wish to try this out yourself.  The assumptions and environment settings are the same as they were in my previous post ( ).

I would love to hear from someone who has an eye for performance tuning!

About Eric Hexter

I am the CTO for QuarterSpot. I (co)Founded MvcContrib, Should, Solution Factory, and Pstrami open source projects. I have co-authored MVC 2 in Action, MVC3 in Action, and MVC 4 in Action. I co-founded online events like mvcConf, aspConf, and Community for MVC. I am also a Microsoft MVP in ASP.Net.
This entry was posted in .Net, Asp.Net, Asp.Net MVC, c#, IIS, mvc, testing, x64. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Eric, I’m almost sure that the issue is what I mentioned by email. When you use multiple view engines, the caching in the primary view engine gets disabled (which I think is an MVC bug). Hence on every request, it tries a bunch of lookups before finding your view. You can see this easily in the debugger, by breaking on all exceptions (and disabling Just My Code). With single engine, you won’t get any exceptions (after the first request, which warms up the cache). With double engine, you’ll get:
    - The file ‘/Views/Home/DateTime.aspx’ does not exist.
    - The file ‘/Views/Home/DateTime.ascx’ does not exist.
    - The file ‘/Views/Shared/DateTime.aspx’ does not exist.
    - The file ‘/Views/Shared/DateTime.ascx’ does not exist.
    - The file ‘/Views/Home/DatePicker.aspx’ does not exist.
    - etc…

  • Victor Kornov

    Hey Eric,

    have you tried to use one composite view negine instead of 2 separate? I.e. you build a vieww engine that delegates to the appropriate web forms or your own InputBuilderViewEngine.

  • @Victor, The single view engine is acting as a composite through inheritance.

    @David, In order to attach the debugger don’t you have to take the debug=”false” out of the web.config? If so than the Caching is turned off and as a result the “more performant” path for the code is not executed. So I guess the next thing to try is to pull down the source for MVC 1.0 make a change to the force the cache to work in debug=true to determine if the exceptions are the problem or the querying of each viewEngine in cache is causing the degradation of performance.

  • Eric, the trick is to start VS without debugging (Ctrl-F5), and later attach to the process (Ctrl-Alt-P).

    Frankly, I hate that MVC changes its caching behavior based on the debug flag. It should be a separately controlled thing. I’ll ask the team to fix that in the next version.

  • @David, in that case than it seems .. for now.. a composition based View Engine is the best approach, as I have discovered by persistence. Thanks for the clarification.