Optimising Umbraco for speed
Heads Up!
This article is several years old now, and much has happened since then, so please keep that in mind while reading it.
Before we start ask yourself if the site even needs any optimisation. I'm a big fan of only doing work if required. If it's a small site with a few macros then it simply might not be worth doing anything. Remember the 80/20 rule and you should be fine.
Macro Caching
First up macro caching. Every time you render a page you cause the macros you've added to that page to run and generate out the HTML we send down the wire. The "thinking time" or more correctly CPU cycles the server needs to do that can be a bottle neck, why spend time working out the menu navigation links each and every page load? It does not change all that often right? So why not work it out once and then save the result and reuse that on repeat request. That's what macro caching does and it's built into Umbraco, you just have to switch it on. We tend to overlook this bit while developing though as we have kick ass machines and we are the only one hitting it.
Warning: Switching on macro caching while you are still developing is not a wise move. At best it can simply slow you down, at worst it can lead to some serious head scratching/violence like so:
while you try to work out why your changes are not appearing on the site. Stay sane, only add it to a staging/live production sites.
Check your macro render speeds. You can get a whole heap of debug information out of Umbraco by switching on the "Debug and Trace mode" by adding ?umbDebugShowTrace=true to the end of your URL, or install the Chrome Umbraco Developer Extension which is really really handy (careful this will only work as long as you have not disabled debugging on the site, by default this is switched on so you know).
Protip: In your sitewide CSS add this rule to make it easier to read the trace output no matter what your background colour is:
#__asptrace {
background-color:white;
}
I've got a whole raft of tips on tidying up trace output but that will have to wait for another day/post, remind me :)
Now at the bottom of the page you should have a huge ugly table of debug output including some lines about Macro render times. There should be a total time up to that point (the 3rd column) and time for that action (the 4th column). Keep an eye out for any macros that are slow (slow to me is anything over 1/10th of a second), we will hit these ones first.
The idea is to hit the slowest macros first, switch on caching for that one, refresh to see the effect and then do the next slowest. The slowest macros should be the ones that are doing the most "work" or are coded really badly...either way caching will help (but try to fix any slow running code first).
Be careful what you cache, it can be really tempting to go through all the macros and set them all to cache. You don't want to cache search result pages for instance (been there, done that). Also, if a macro is rendering in 1/100th of a second it's not really a snail now is it? Leave it be unless you are super keen or bored with having a life outside of work. An exception to that is if the site only has a fraction of the data in it (let's say it's just got a bit of dummy content in it) then you might not be seeing "true" render times that the live site might experience. Another good reason to only really setup macro caching on a live/staging site.
So to get to macro settings you need to go to the Developer > Macros and select your slow macro. If you can't see the Developer section then you don't have access (if you're a client, stop trying to mess with the site, you'll break something!).
The important setting is "Cache Period", by default this is set to zero which means don't cache. The number here is the number of seconds you want to cache the output for. Simply change this to a valid number (try 10 seconds for now), leave the other settings as is ("Cache by page" checked and "Cache Personalized" unchecked), save the macro settings and that's it. The macro will now cache itself the next time it runs and won't refresh itself until the number of seconds you added have passed. Reload your page and you should see next to no difference because it still has to generate the output the first time, reload again and now the output will be pulled from cache super fast!
How long to cache for? Depends really. Any caching can make a huge difference. You can go the route of micro caching for just a few seconds, or if the content really does not change that much, you can bump the time up some more. Even quiet sites can benefit; headers, navigation etc. will be re-used during a user's visit. They might be the only visitor that day but each page they visit after the first one will have cached content so will appear faster.
Caching makes the site faster and reduces load on the servers (especially important on a busy site). We are trading memory space for CPU cycles here so make sure your site has enough memory to cope, IIS will handle the memory for you but to make the most of caching you should have enough memory to store all the different output in. The cache will expire if the site is not hit for 15 minutes (as IIS shuts down the app pool to save resources) or if the app pool recycles for some reason. You can get around this by polling the site every 10 minutes or similar from another server/service but ask yourself if that's really all that important/required before doing it defacto.
Compress your images
Another nice simple mod you can do is to compress your images. This is easy enough to do when building the site but harder when you hand the site over to clients who start uploading HUGE jpg files from their digital cameras or that they have found somewhere in an uncompressed state. All that hard work ruined by those pesky clients.
ImageGen to the rescue as ever. This awesome image resizing script ships with Umbraco so you can use it on any build. The freebie version is up to the job too (however, if you've ever used ImageGen and not bought at least one Pro licence, you really ought to think about it on the next project, Doug deserves it). You don't have to use it just to resize images though, you can also use it to compress them.
ImageGen resizes images based on the values you pass in on the query string and out of the box does a great job of compressing images too, but you can tweak this a little more if you want. There is a little known setting called "Compression" which can be used with jpg images.
This is the amount of compression as a percentage that you would like to apply to the image. The default is a rather high 90%. You can pass through a lower value however and make some really good savings on file size for very little loss of quality. The range of 72-80% seems to work for me, depends on the type of images your client mainly use.
(original, 611K)
http://offroadcode.com/media/14930/original.jpg
(90% compression by default, 156K)
http://offroadcode.com/umbraco/ImageGen.ashx?image=/media/14930/original.jpg
(75% compression, 140K)
http://offroadcode.com/umbraco/ImageGen.ashx?image=/media/14930/original.jpg&compression=75
By default always use ImageGen to render out any images that the client can change, it will help save a lot of bandwidth. Tweaking it via the compression option can save some more for an extra gold star.
Hope that gives you something think about and some pointers on where you could make some saves. There are plenty of other tips but these two are Umbraco specific which is what these posts are all about. Hope you enjoyed it, if so feel free to buy me a beer next time we meet.
Festive greetings to you all, my extended Umbraco family :)
Pete
Pete Duncanson
Pete is on Twitter as @peteduncanson