A file (and memory) based cache of expanded templates
I started from a patch uploaded to
TWiki:Codev by Sven a long time ago. He described it as optimistic, I have completed it to make it realistic and added memory caching as well (to take advantage of any persistant execution). Attached is the first fully working version of the code,
filememcacheTemplates.pm
(please note that I am not a Perl programmer (or any type of programmer) of any training whatsoever, and that I developed this on a TWiki installation and simply ran the file through the
twiki2foswiki
script before uploading here - so no foswiki testing as yet).
Note also, that the following would have to be added to the end of
saveTopic
repRev
and
delRev
in
Store.pm
if( $Foswiki::cfg{CacheTemplates} && ($topic =~ /Template$/) ) {
# delete cached templates if they're built on a Template topic that has just been saved.
$this->{session}->templates->deleteTemplate($topic, $web);
}
Is template expansion expensive?
In the new code, the memory cache is checked first, then the file cache and then, only if no success, is the normal expansion path followed. When a new template is expanded, it is written out to a cache file and added to the memory cache. Where a user defined template is being requested, view access rights to that template are respected. The dependancy tracking gets a bit ugly in places, but it does work.
All pleased with myself, I started writing this up as a feature request, but in the middle I thought I'd better do some objective benchmarking and was rather surprised. See below. I also went back to an earlier version of the code which only used a file cache (
filecacheTemplates.pm
attached) and did the same tests.
Not the results I was hoping for...
My server is running in a JeOS VM with Speedy. For each of the tests a single speedy backend was established beforehand, the file cache for the requested page was also established. The values below are the mean values for each of seven consecutive runs per configuration.
filecache with caching enabled
Requests per second: |
0.26 |
0.26 |
0.26 |
0.27 |
0.26 |
0.26 |
0.26 |
Time per request [ms]: |
3870.800 |
3864.181 |
3872.540 |
3756.496 |
3794.151 |
3793.519 |
3789.042 |
filecache with caching disabled
Requests per second: |
0.25 |
0.25 |
0.25 |
0.25 |
0.25 |
0.25 |
0.25 |
Time per request [ms]: |
3928.968 |
3946.436 |
3978.547 |
3960.525 |
3971.398 |
3966.494 |
3961.313 |
filememcache with caching enabled
Requests per second: |
0.27 |
0.27 |
0.27 |
0.26 |
0.27 |
0.27 |
0.27 |
Time per request [ms]: |
3714.610 |
3729.613 |
3742.136 |
3775.863 |
3752.785 |
3755.988 |
3766.135 |
filememcache with caching disabled
Requests per second: |
0.26 |
0.26 |
0.26 |
0.26 |
0.25 |
0.26 |
0.26 |
Time per request [ms]: |
3904.932 |
3892.773 |
3892.262 |
3905.932 |
3924.663 |
3901.703 |
3910.633 |
original Templates.pm
Requests per second: |
0.25 |
0.25 |
0.25 |
0.25 |
0.25 |
0.25 |
0.25 |
Time per request [ms]: |
3947.066 |
3936.297 |
3926.656 |
3927.146 |
3938.757 |
3938.379 |
3957.326 |
Conclusions
Either my code is crap (I've worked out all the checks and balances required for dependancy tracking but it is a bit sledgehammer-ish), or the template expansion isn't that heavy afterall
--
Contributors: DavidPatterson - 23 Jan 2009
Discussion
Urgh! The code doesn't handle properly the situation where a user defined template is TMPL:INCLUDEd by another template: the template would then be, or not be, expanded in the cache depending on the access rights of the first user to come across this template, and any subsequent user would only see the template from the cache. The most efficient way of dealing with this, I think, would be to unset a
cacheme flag whenever a user defined template is included during the expansion so that the toplevel template is never cached. Unfortunately, however, this would mean that the comments template is never cached. In
FoswikiCache Michael talks of dirty areas, it seems that Foswiki's strength is its weakness when trying to do any optimization like this: too much configurability.
For any Admins out there, it is, perhaps, worthwhile to do a little tidy up of the $Foswiki::cfg{TemplatePath} variable: the option of a single skin having different versions per web is deprecated and none of the major skins supports this, so there are two options on the path that can be removed. Decide for yourselves if there are other options you can get rid of (the down side is that any changes you make would have to be reported and maintained on the Skins pages in the doco). Every little helps...no?
--
DavidPatterson - 24 Jan 2009
well done
one thing to note is that It looks like you've done the stats on a lightly loaded mainstream system, and the original analysis I did was by massively overloading a sun t2000 with slow 2.5inch disks - and in that case, caching the templates made a big difference to how long the server stayed up before being DOS'ed.
The
nice thing about caching is that you create a fast path for normal operation without removing the customization - but as you found, the writer of the cache has to be clever
--
SvenDowideit - 25 Jan 2009