Hello all,
To keep threads a bit on topic, I thought it would make sense to open a new one for caching.
Ryan asked me about my ideas on caching, which you can find in the recursive parser thread, due the fact I did a number of profiling tests.
The discussion in the recursive parser thread was about partial caching, calling conventions etc.
I actually would love to sit around a table with other people discussing these kind of stuff, instead of writing down into a forum, but oh well.... ;-)
Ryan added some nice weblinks there, and one was particularly interesting:
php scripts serve dynamic pages, but not all parts of a page are dynamic, so the non dynamic parts are cached to improve performance
Or something similar was stated there.
Raymond also explained nicely how partiall caching is working with the [! !] calls.
The point is however, why do we want people to _force_ partiall caching?
For example, in a template, we call [!DropMenu!] so we are sure if a new page is created, it will show up in the menu...
So, in other words, we _force_ all the pages with that template to have the Menu part recreated each and every time the page is requested, even if _nothing_ in the database changed, which will be most of the times those pages are requested, no?
This results in _significant_ performance degradation over just caching the whole page _including_ the generated menu.
However, there are snippets/others that _needs_ to be generated each and everytime a page is requested, like snippets containing a form, or a username stored in a coockie.
It makes sense to cache a generated page, but _not_ store the evaluated snippet, but leave the snippet call there, in whatever form (the recursive parser will catch it always, no need to have a different format)
So what about adding a property to a snippet in the manager, or a system call a snippet creater can call from within the snippet like:
Or a checkbox on the snippet page in the manager.
At page creation time, depending on this variable, the snippet ouput is stored in the cache page, or the snippetcall is put back again/left there.....
Now, if the state of the database changes, the allready cached pages will be obsoleted, and regenerated the first time they are requested again.
You might ask "but partial caching would improve the situation a bit, since the page content is allready in cache, and doesn’t depend on the state of the database!"
Thats correct, but from what I’m seeing here, the snippets consume a large part of the page creation time, so the difference between a ful newly created page, or a partiall cache page isn’t really much.
AND, after the page is created, it can be served as a true cached page, without any snippet to be evaluated for as long as the database doesn’t change!
Compare that to the slightly faster _first_ creation of the page with partiall caching, with continuously degraded performance for all the other page requests for as long as the database doesn’t change....
Fancy/complex/arrays of states/whatever way you want to "detect" if a page can be served from cache, partiall or not will add time to _every_ request for a page, even if it can be served _completely_ from the page cache.
Adding one time stamp in a flat file with the time the database was lastly changed, and the page creation time stamp in the page cache file, that would be fast no?
Just one if statement, and if true, the page is recreated from database, and not true, the page is served from cache, _and_ the recursive parser is run over the cached page to evaluate those snippets which are forced to be non cachable (given by a parameter set by the snippet _creator_, not the person who inserts the call into a template)
Now, there is a little problem with for example this:
[[DropMenu? startDoc=[[*lang]] ]]
In this case the [[*lang]] depends on a cookie, so the creator of this snippet decided it should be non-cachable.
Right, but the DropMenu doesn’t know this, and _is_ cachable, so we have a problem here.
Not sure how to code it yet, but from within the recursive parser, it should be possible to return the "is cachable" bit for nested snippets, and if there is a non-cacheble nested snippet, the "parent" snippet will be set un-cachable too....
So, this way, partiall caching works transparantly for the user, and only the snippets which are really non-cachable will not be cached.
Pages will almost always be served from a completely cached page cache, greatly improving the parsers speed.
Of course, I could be totally wrong
Remon