Performance tips

Relatude has an extremely efficient cache built deeply into the core of the system. That means that you in many situations don't have to worry about performance, but in certain situations you need to optimize the template rendering, here are some great tips!

A number of factors affect the page rendering speed at the end client. This article focuses on the server execution time. Other factors like number of images you have on the page, order of HTML elements, javascripts, network latency, network speed etc. are not covered. These are generel HTML/HTTP topics covered well in other articles on the web.

Test the performance of your template code

Try adding "?WAFPageTimer=true" to the request url on any page. You'll get back information about page rendering in ms. Generally the average page rendering should not exceed 200 ms, this will start to limit the overall capacity of the server (1000/200 = 5 pageviews per sec per CPU) and the user will start to notice some delay on a fast internet connection.  

Never make queries using with the DateTime.Now as a parameter

These queries cannot be cahed efficiently and can potentially result in a new SQL every second. Workaround: use a DateTime variable that only changes every hour like this for instance: DateTime.Now.Date.AddHours(DateTime.Now.Hour) . (Or even every minute is better than every second)

Avoid synchronous calls to external websites

Like RSS, Web services etc. Workarounds: Cache the result in an application wide variable updated on the first request each hour or better, use a scheduled task to update the data in the background. 

Query only for relevant data

This is kind of obvious, but still often forgotten. Check the number of objects retrieved during a page request using the "?WAFPageTimer=true" parameter. Try to stay below 1000. Badly written functions that renders hierarchical menues are often a good place to start looking. Remember to always add paging to larger queries. Do as much of the filtering as possible in the AQL query, do not leave to much of the processing to in memory LINQ queries and similar. 

Avoid too many joins in one statement

Consider de-normalizing the data. You can build complicated and nested joins with the AQL Query objects, but these joins can load the database heavily. As a general rule try to avoid more than 4 types in one query, especially if you are dealing with a database with more than 100 000 objects and it is difficult to cache the queries effectively, due to frequent updates or date based filtering. The workaround is to de-normalize parts of the data, this normally means storing certain information more than once in the database. Add hidden fields to the objects that are updated automaticall in the relevant content events like "OnBeforeUpdate".

Push as much work as possible onto the client

Any heavy processing or requests to other servers that you can load onto the client will scale much better than doing it on the server. Typical examples are feeds. Lazy loading these data in javascript is really fast. There are several tricks to avoid security warnings related to cross domain requests. A simple workaround is to put heavy content from other servers in iframes.

Use output cache on heavy data in masterpages

The built in ASP.Net page cache is very fast, but is mainly time based and therefore not ideal for all use cases. Generally this cache is a good last tuningoption on pages with really high traffic loads and infrequent updates.

Optimize the cache size

Tune the size of the cache size to the memory you have available. The default settings allows for a lot of memory usage, so if you are hosting many installations on one server it makes sense to tune each one. The size limit is specified in web.config:

    <add key="WAF.QueryCacheLimit" value="10000" />
    <add key="WAF.ContentCacheLimit" value="10000" />