Blog: Fixing a slow Umbraco site
A slow Umbraco site can be difficult to diagnose. At Moriyama we’ve years of experience in doing this. We offer a health check of your site which includes a fixed cost diagnosis of performance issues - if the content below is a little too technical.
Is it only slow in production?
If your slow Umbraco site is fine on your staging server or the developer PC then this points to issues of concurrent user access to the site. You may wish to read our other blog on diagnosing and fixing 100% CPU spikes to find out about common issues that cause performance problems with multiple users accessing a site - heed the advice in that article and try to upgrade Umbraco if you are running an old version.
It may be that in your production environment latency between Umbraco and SQL server is high compared to the developers PC and/or disc IO is slow. For example, Azure web apps has slow disc read/write compared to a development PC.
A well written Umbraco site should run almost entirely from the memory based content cache - some implementations may suffer from custom code where the developer hasn’t fully understood the architecture of Umbraco and added lots of custom SQL.
How you benchmark SQL latency and disk I/O depends on whether you use dedicated/VPS servers or some kind of cloud abstraction - but for regular hosting SQL server profiler (part of management studio) will show the queries that your site is running and how long they take.
You could also install a tool like NewRelic or LeanSentry both inproduction and locally to benchmark common queries.
People often think that a slow Umbraco site can be fixed with a faster server or a more powerful database, but unless your site commonly has more than 50-60 concurrent users this is rarely the case (you can use live google analytics to see how many people are on your site).
It is slow locally too!
In a way, this is good as it makes your slow Umbraco site easier to diagnose.
Begin by eliminating custom code from the Umbraco request pipeline - compare your web.config file with one that is released with Umbraco to see what has been added. If you see additional httpmodules or httphandlers - try to temporarily comment them and see if this has an impact on performance (we’ve identified issues with popular Umbraco packages in the past).
For comparing files - Beyond compare is excellent.
The next test that we would perform would be to empty the Umbraco templates and run the site without any HTML or CSS at all. It is fairly easy to write a script to blank out templates and later restore them.
If you’ve been through the steps above and you still have a slow Umbraco site then you’ll almost certainly find that your site is fast now.
Gradually re-introduce functionality into your template and see when the site slows. When you identify the component of the page that causes an issue - inspect and refactor the code.
As a quick and temporary fix you could consider Macro caching, Umbraco’s Html.CachedPartial directive.
You could also look at MVC output caching and donut caching - though these could have knock on effects for your site and you should be fully versed in the nuances and intricacies.
Common mistakes
We see a few common patterns in custom code added to Umbraco - which end up causing performance problems:
Excessive Linq: Loading large sets of data into memory and filtering isn’t a great idea - and also doesn’t scale - what was fast with little or no content, can slow down exponentially.
Excessive Log4Net logging: There is plenty of good material on the internet about how and when logging should be used.
Misunderstanding of sleep and lock: If your codebase contains Thread.Sleep and the locking of objects - you should be completely confident that you understand why you are doing it and that it is necessary. In most common website scenarios, sleep and lock can be refactored.
Joining Examine and other data: Lucene is not a relational database and shouldn’t be used as such - if you have code that queries Examine and then filters by Linq and/or adds data to the results from other sources, you likely need to redesign the functionality.
Querying the Umbraco database to retrieve content: This is the number one Umbraco cardinal sin - Umbraco content should be retrieved from the Umbraco memory cache, using the Umbraco API.
The site used to be fine!
On a site that has “matured” over time it important to audit your content versions from time to time using Umbraco.
Also consider upgrading if you have a very old version of Umbraco.
The site starts slowly - but is fine once it is up!
There is an overhead in starting up Umbraco - primarily comparing the disc based cache to the database to make sure it is up to date and also making sure that the Examine indexes are built.
You can prevent Umbraco from building Examine indexes at startup by adding the RebuildOnAppStart property to the configuration - and manually rebuilding the indexes from the developer section of Umbraco if required.
If you don’t use Examine, disable the indexes that you don’t use - though Umbraco requires the Internal indexes.
This is all too techie!
If you’d like Moriyama to help fix your slow Umbraco site, call us for a fixed cost quotation.