How do you improve your ASP.NET MVC application performance?
Not an earth shattering optimization but I thought I'd throw this out there - Use CDN's for jquery, etc.
Quote from ScottGu himself: The Microsoft Ajax CDN enables you to significantly improve the performance of ASP.NET Web Forms and ASP.NET MVC applications that use ASP.NET AJAX or jQuery. The service is available for free, does not require any registration, and can be used for both commercial and non-commercial purposes.
We even use the CDN for our webparts in Moss that use jquery.
Basic suggestion is to follow REST principals and the following points ties some of these principals to the Asp.Net MVC framework:
- Make your controllers stateless - this is more of a 'Web performance / scalability' suggestion (as opposed to micro/machine level performance) and a major design decision that would affect your applications future - especially in case it becomes popular or if you need some fault tolerance for example.
- Do not use Sessions
- Do not use tempdata - which uses sessions
- Do not try to 'cache' everything 'prematurely'.
- Use Forms Authentication
- Keep your frequently accessed sensitive data in the authentication ticket
- Use cookies for frequently accessed non sensitive information
- Make your resources cachable on the web
- Utilize ETags
- Use expiration
- Write your custom ActionResult classes if necessary
- Utilize reverse proxies
- Compile your Javascript. There is a library to do it as well. (sure there are others too)
- Use CDNs - especially for your large media files and so on.
- Consider different types of storage for your data eg. files, key/value stores etc. - not only SQL Server
This is nice presentation about ASP.NET MVC performance:
http://codeclimber.net.nz/archive/2009/04/17/how-to-improve-the-performances-of-asp.net-mvc-web-applications.aspx http://blog.whiletrue.com/2009/04/aspnet-mvc-performance/
Compiled query will increase performance of your application, but it has nothing in common with ASP.NET MVC. It will speed up every db application, so it is not really about MVC.
When accessing data via LINQ rely on IQueryable ...
http://stackoverflow.com/questions/1106802/why-use-asqueryable-instead-of-list
... and leverge a good Repository pattern:
http://stackoverflow.com/questions/1223194/loading-subrecords-in-the-repository-pattern
This will optimize data access to ensure only the data needed is loaded and when only it is needed.
A compiled list of possible sources of improvement are below:
General
- Make use of a profiler to discover memory leaks and performance problems in your application. personally I suggest dotTrace
- Run your site in Release mode, not Debug mode, when in production, and also during performance profiling. Release mode is much faster. Debug mode can hide performance problems in your own code.
Caching
- Use
CompiledQuery.Compile()
recursively avoiding recompilation of your query expressions - Cache not-prone-to-change
content using
OutputCacheAttribute
to save unnecessary and action executions - Use cookies for frequently accessed non sensitive information
- Utilize ETags and expiration - Write your custom
ActionResult
methods if necessary - Consider using the
RouteName
to organize your routes and then use it to generate your links, and try not to use the expression tree based ActionLink method. - Consider implementing a route resolution caching strategy
- Put repetitive code inside your
PartialViews
, avoid render it xxxx times: if you end up calling the same partial 300 times in the same view, probably there is something wrong with that. Explanation And Benchmarks
Routing
Use to 'Url.RouteUrl("User", new { username = "joeuser" })' to specify routes. ASP.NET MVC Perfomance by Rudi Benkovic
Cache route resolving using this helper 'UrlHelperCached' (enter the link) ASP.NET MVC Perfomance by Rudi Benkovic
Security
- Use Forms Authentication, Keep your frequently accessed sensitive data in the authentication ticket
DAL
- When accessing data via LINQ rely on IQueryable
- Leverage the Repository pattern
- Profile your queries i.e. Uber Profiler
- Consider second level cache for your queries and add them an scope and a timeout i.e. NHibernate Second Cache
Load balancing
Utilize reverse proxies, to spread the client load across your app instance. (this site for example use HAProxy (MSDN).
Use Asynchronous Controllers to implement actions that depend on external resources processing.
Client side
- Optimize your client side, use a tool like YSlow for suggestions of your work.
- Use AJAX to update components of your UI, avoid to update the whole page when possible.
- Consider implement a pub-sub architecture -i.e. Comet- for content delivery against reload based in timeouts.
- Move charting and graph generation logic to client side if possible. graph generation is a expensive activity. deferring to client side frees your server from an unnecessary burden, and allow you to work with graphs locally without make a new request. i.e. Flex charting, jqbargraph, MoreJqueryCharts
- Use CDN's for scripts and media content -and so on- to improve scripts loading in the client side. i.e. Google CDN
- Minify -Compile- your JavaScript in order to improve your script size
Also if you use NHibernate you can turn on and setup second level cache for queries and add to queries scope and timeout. And there is kick ass profiler for EF, L2S and NHibernate - http://hibernatingrhinos.com/products/UberProf . It will help to tune your queries.
IN addition to all the great info on optimising your app on the server side I'd say you should take a look at YSlow, it's a superb resource for improving site performance on the client side.
This applies to all sites, not just ASP.NET MVC.
One super easy thing to do is to think asynchronously when accessing the data you want for the page. Whether reading from a web service, file, data base or something else, use the async model as much as possible. While it won't necessarily help any one page be faster it will help your server perform better overall.
This may seem obvious, but run your site in Release mode, not Debug mode, when in production, and also during performance profiling. Release mode is much faster. Debug mode can hide performance problems in your own code.