The CMS Squad just rolled out some updates for the Partial Template Caching documentation.
Particularly, we’ve made a separate doc explaining the template tag mechanics in depth and refined the performance recommendations.
Another recommendation which is not included to the CMS documentation:
DO NOT cache Elemental Area. Consider caching every separate block instead (where it is appropriate). Especially if you have silverstripe/userforms installed. User data may be leaked through the cache, which is a potential security issue.
If we missed something interesting, please share your recommendations in this thread, or consider making a PR for the CMS documentation:
Avoid heavy computations in cache keys and conditionals
Is there a built in way to debug this? Does the framework keep track of the overhead on each request that is spent calculating partial caching cache keys?
@dnsl48 I think there’s another important thing you could note in the docs. When I read this my heart sank:
Be careful using aggregates. Remember that the database is usually one of the performance bottlenecks. Keep in mind that every key of every cached block is recalculated for every template render, regardless of caching result.
I tested this, and it’s true. I assumed that if you used the same aggregate in a template twice it would only be calculated the first time, as that’s what I’m accustomed to when calling other methods in a template. But identical database queries are fired off multiple times.
However in my case, it didn’t matter, because I do all my cache key calculations in the controller. Because I’m using controller methods, their result is cached and reused, so I can use the same cache key fragment in multiple cache blocks without penalty.
/**
* Get a cache key which get the approximate state of a class.
* Will not capture things like sort order if changes bypass the ORM.
*
* @param string $class
* @return string
*/
public function ClassCacheKey($class)
{
return __FUNCTION__ . md5(serialize([
$class,
$class::get()->max('LastEdited'), // Catch created / edited
$class::get()->count(), // Catch deleted
]));
}
And you don’t get duplicated SQL queries.
BTW in case it’s useful to others, I made a gist of the partial caching controller methods I’m currently using:
No, we don’t have a dedicated debugging for template caching yet. The easiest way would be to use debugbar and see the repetitive SQL queries. However, I guess we could add extension points around the cache key generation and debug it more granularly. I’ll think about making a patch for the SS Viewer components and later we could pick it up in Debugbar.
if you used the same aggregate in a template twice … identical database queries are fired off multiple times. However in my case, it didn’t matter, because I do all my cache key calculations in the controller. Because I’m using controller methods, their result is cached and reused, so I can use the same cache key fragment in multiple cache blocks without penalty.
That’s a good gotcha. Here’s a PR to add it to the documentation.
Hi @obj63mc, you’re using it the way I intended (I assume I tested this but I don’t remember writing the code anymore, you know how it is ). You have a typo in your post - ListCasheKey instead of ListCacheKey - is it possible that’s the issue?
Another option is to add an extension to DataList, something like this. Then you can do e.g. <% cached $MyList.CacheKey %>
That was just a typo from me typing here, confirmed code is like -
<% cached $ListCacheKey($MyList) %>
If I try to add a dump in the function like -
public function ListCacheKey($dataList){
var_dump('here');
exit;
It never gets there. Will try an extension on datalist, seems like that would work well. Biggest thing for me is trying to cut back on some of the duplicate query calls for a site I am running with like 40 different data models and thousands to hundreds of thousands of records so far.