Thursday, June 6, 2013
Some techniques to improve your Umbraco site performance, ultimately making it run faster and be less demanding of the CPU and Memory.
Some improvements will be through a simple configuration of Umbraco features that we often neglect due to project deadlines.
I’m going to split this article into 2 topics, the CMS and Integrated Web services.
Create and reuse your Helper class
With the most recent version of Umbraco I believe most companies shifted their development to Razor.
So this is where our first tip comes. With all the ways to get content I do like to use Umbraco’s DynamicNode due to their handy methods and default properties for a content node.
Although its a good class to use, it does not always have everything that a normal Umbraco site would require. For this we take a more classical approach, used in most development, create your own “DynamicNodeHelper” class with static methods that will help you take care of exceptions and help you maintain your razors scripts cleaner.
We create this class under the App_code folder.
Some good examples of handy methods:
- DynamicNode GetParentByLevel – If you want to get a parent node assuming you have a defined structure for your content;
- DynamicNode GetParentByNodeType – A better way to get a parent when a certain type of parent can be repeated through your site;
- List<DynamicNode> GetAllVisibleChildrenByType – Get all visible children of a certain type, its also used to do extensive queries that usually would take a good amount of code space on a Where condition;
- string GetHTMLStrippedContent – Usefull to strips RichText properties to use in some other part of the site witouth the need to create an extra property for a summary;
- DynamicNode GetNodeByTypeAndName – Get any node by its type and node name for when you have multiple nodes with the same type trough the site like a Seetings Item;
- Bool PropertyExists – Simple way to just verify if a property exist on a node to avoid exception errors;
- Media GetMedia – When you select a media item on a content node it just stores its Id, this kind of method helps you taking care of exception handling and a help you have a cleaner code.
These are just examples for the use of this Helper. It won’t make a big difference in performance but its a good way to keep you organised and have something to reuse for your future projects.
Use Macro Cache when possible
Except when you have content being filtered by query strings or other “external” inputs, this is a good way to improve the response times of your pages, especially on content heavy pages.
This can be done on the Macros settings in Development section:
Just a good 60 seconds should already make a difference, you can leave the rest of the default settings as they are.
Don’t forget to advise the Content Manager and make sure in testing that a page does not get stuck when changing a filter for it.
Integrated Web Services
Tweak your cache
Since Umbraco was build in .Net its relatively easy to integrate web services under the same solution.
There are plenty of examples where this integration can be useful. One of them can be a “cms-web services” integrated solution that can retrieve content, serve media files, edit new content.. you name it, to a Smartphone App. Particularly in this case you might want to test the responsiveness and performance of services on the server. Do stress tests and think about how up-to-date the retrieved content must be for your App.
Phones and mobile internet connections are still not resilient so the speed of how you perform your logic rules, queries and retrieve data is a very important factor. No one wants the client making a request for data and the response taking 15 seconds, in which time connectivity might be lost.
Of course, the quality of your code is important to this, keeping your business logic tidy is essential, but still there are some other things that you can do that will not just help you make your services run faster but also eliminate possible concurrency issues.
You can manage the thread pool to take of this, use a singleton, but Umbraco can be very efficient by just tweaking some settings in the file umbracoSettings.config.
We are going to modify the cache management of the system, since it can be heavy and even throw exceptions under heavy queries to the content, mainly due to rights to read and write to their xml cache files with several threads coming at once.
So this is the list of settings you should change in umbracoSettings.config:
<!– Enable / disable xml content cache –>
<!– Update disk cache every time content has changed –>
<!– Cache cycle of Media and Member data fetched from the umbraco.library methods –>
<!– In seconds. 0 will disable cache –>
Note: Do not forget to delete the umbraco.config under App_data folder and restart your app.
Now comes the tricky part. If you were using DynamicNodes or Nodes from NodeFactory you might want to forget them. With these settings these two ways of content retrieval won’t have the latest content. The only way that I found to retrieve up-to-date content is to restart the site service.. not good.
But don’t worry! You can dip your teeth into the umbraco business logic Document. You can use this class to both retrieve and create new content when at the same time you’ll have no problems retrieving the latest data.
Of course you’ll have to modify a your code, adjust the way to take care of the content since it will not match 100% the same strings it was returning with the DynamicNode (eg a selection of a dropdown property will give you the id of the selected value instead of the value itself like a DynamicNode would give).
You may like to preserve the same amount of cache time as you have for your macros, to keep coherence and to improve further the performance of your request.
I suggest you build your own Cache Helper for this and use the same amount of time you’re probably using on your Macros.
The call will be under the normal response time, but the subsequent ones will just fly.
Make sure you use it on the right web services as well, you probably don’t want to use it on light web service calls or when up-to-the-second content matters.
This concludes this article. It could be a bit more depth in detail but it would defeat its purpose. Please feel free to leave a comment, send an email to us. You can contribute to it, ask for details, also let me know if you don’t agree or have a better approach, we are “all ears”.
Send us a comment on this article