07May2012

The most frequent error in Fatwire site development

One of the more frequent mistake in Fatwire Development  that I have seen so far is overlooking the caching behaviour of render:calltemplate.

This mistake is so frequent that I take it for granted. It is always the first thing I check. I have seen it  almost in all the project I was consulted for support. The usual symptom is  that have performance problems.

Unfortunately, it can be a devastating error if discovered too late. Because calltemplate is ubiquitous, if you used it incorrectly you may have to revisit the code of your entire site, if not a complete rewrite.

In a nutshell, the behaviour of render:calltemplate is: retrieve a cached element if it is available, or execute the code to generate the html, then cache its output. In general, in 99% of the cases, calltemplate should NOT be executed: it should instead return a cached element. This behaviour has a deep impact on the way template code must be written.

If you write your code incorrectly, the  template cannot be cached. As a consequence, performances will be very bad, because retrieving content from the database is very expensive. This is the whole reason because there is a caching in place: avoiding to retrieve content from the database every time.

What render:calltemplate really does

Probably the name of the tag itself is misleading: many developers thinks that calltemplate will actually always CALL a template every time. It actually does not always happen.

Calltemplate takes all the parameters  it was called with , order them in alphabetical order and build a string like c=xxx,cid=yyy,p=zzz,site=xxx,... (note the alphabetical order to make sure that you do not have cid=yyy,c=xxx different from c=xxx,cid=yyy when you have the same xxx and yyy))

This string is used as a key for the cache, then the cache is looked for. If a cached element is found, the cached output is returned. Otherwise, the referred template is invoked and the code executed. I cannot stress more that in general executing a template can be very expensive, performance wise. Getting attributes from the database may require a lot of queries, many of them involving a join (another expensive operation if you have large tables).

To get high performances, in general you should try to get zero calls to the database in 99% of the calls.

Each template has a list of parameters that will be used as "cache criteria". When you call the template, the list of parameters is checked against this cache criteria. If you call a template with a parameter that is not listed as a cache criteria a warning in the log is generated.

Please note that instead the render:callelement has a different behaviour: it is always invoked and it is usually used to invoke standardized html generation logic.

You do not have restrictions on the arguments you pass to a callelement, because its output will not generate a separate cached element: instead its output will cached as part of the calling template. Of course if it is database intensive then it will have bad performances.

What you cannot do in a cached template

Given this behaviour, there is a number of coding practice that are forbidden

First and before all, side effects. You cannot set a variable in the environment (something like ics.SetVar("flag", "something") and use it as an implicit parameter for a called template. Something that instead you usually have to do to use a callelement to retrieve informations. Side effects are actually the only way to get return values from an utility element.

Because the template can be cached, all the parameter must be explicitly stated, otherwise you may get the wrong template. The implicit paramente will not work unless the template is uncached (and this is not good for performances).

Another mistake is using a parameter that can change too often. For example, you may pass an uniquely generated id  to a template.

Even if this id is correctly added to the cache criteria, the problem here is that a different id will create a new cached element every time the template is invoked. If you have a site with millions of users, you will end up generating a new cached element for each request!

The result here is a that the cache can became very large. I have seen sites with id passedin absolute freedom growing the cache at the rate of one thousand elements per minute!!!

This mistake will affect performance, but even worse  publication. Because publication involves invalidating the cache,  with a cache out of control, invalidating may take hours…

 

 

Posted by msciab
07May2012