This enhancement stems from valuable feedback we got from the market. Many times, adopters of eZ Publish knocked on our door to tell us they had performance issues when lots of content editors were (hyper)active on their eZ Publish-based application.
Introduction
For those who are not familiar with the details, let's brush up on the background information required to understand the problematic they stumbled upon. As an example, when displaying a content object, say in 'full' view mode, eZ Publish stores the HTML resulting from template processing ( or “caches it” ). That is called the “View Cache”, which will be re-used next time the piece of content is displayed the same way. This prevents from processing the display templates every time the content object is displayed, significantly alleviating load on the application. This system has been in place for a long time now ( slightly before 3.0 ).
In order for the displayed content to be in full sync with the actual content as real-time as possible, the View Cache for a content object is expired when a new version of the object is published. That means that the “cached” HTML needs to be refreshed, causing the display template to be processed anew the first time the content object is displayed in its new version. More information can be found here: http://ez.no/doc/ez_publish/technical_manual/4_0/features/view_caching.
The “View Cache” is taken as an example here, but improvements brought by the Stale Cache feature also apply to Cache Blocks and other types of cache. And please also note that this feature applies to non-cluster modes as well as cluster modes.
When several concurrent users are requesting the same object, for which the View Cache just expired, requests are queued, only the first of them triggering the View Cache regeneration. This implies that nearly all requests received at this specific moment ( except the very first one ) will be waiting for the fresh cache to be available, raising two major drawbacks :
- User experience level : clients are waiting at least the time needed to recreate a piece of cache, which can take a long time when complex templates are in use.
- System level : all these queued requests put a lot of pressure on the system's resources ( race conditions, deadlocks, ... )
Solution
Instead of letting these queued clients wait until the new version of the cache is ready ( and stress the servers ), why wouldn't we show them the former version of the cache ? This case would not happen very often, and who would be the most unsatisfied client : the one waiting 20s for a page to be displayed, or the one seeing a former version version of it once or twice, and the updated version a few seconds later ? Well, that is a trade-off between user experience and content freshness, and going for the solution where user experience is maximised, and content freshness gracefully degraded, sounded like the way to go.
That is what “Stale Cache” is all about. It brings a much smarter cache-handling, significantly improving the overall performance of a website, both being user-centric and system-friendly.
Implementation
Let's dig into the implementation details of Stale Cache....WARNING : Jargon alert :)
Below is presented the state machine of the Stale Cache feature. As “an image is worth thousand words”, we made this diagram as self-explanatory as possible.
Note that this behaviour is natively embedded in the eZDB cluster file handler, meaning that any clustered eZ Publish instance directly benefits from Stale Cache. However, due to a PHP limitation on Windows, concerning the touch() function ( http://www.php.net/touch ), Stale Cache is not enabled by default on the non-clustered eZ Publish instances. If you are not running Windows, or if you upgraded to PHP 5.3 at least and are running Windows, it is strongly recommended to enable Stale Cache. It is shipped in an alternative to the eZFS file handler, called eZFS2, which can be enabled through the following process :
- Edit an override of file.ini ( called file.ini.append.php ).
- Under the configuration block called '[ClusteringSettings]', set the value of the 'FileHandler' directive to 'eZFS2FileHandler'. In the end, your file.ini.append.php might look like this :
<?php/*
#?ini charset="utf-8"?
[ClusteringSettings]
FileHandler=eZFS2FileHandler
*/
?>
Clear caches, and there you go...check the ' Results' section if you still are not convinced !
Results
We ran series of benchmarks to evaluate the influence of the Stale Cache feature on a website's overall performance and user-experience. One of them consisted in using a JMeter scenario to hammer a specific page, simulating 20 concurrent end-users viewing a fully-cached content node, during one minute. We stressed two very identical instances of eZ Publish, but for the Stale Cache improvement. We wanted to measure the impact of a view cache re-generation under high load and high concurrency. During this minute, the content object's view cache was cleared 8 times. Here is the resulting graph ( volume of requests/sec on the vertical axis ).
The obvious trend on this graph it that upon every cache clearing, with no Stale Cache, eZ Publish's reactivity shrinks down to 40 requests/sec, while being slightly over 60 requests/sec in average otherwise. This is due to the now defunct sub-optimal queue handling in cache management, which frequently resulted in DB deadlocks or other harmful race conditions. As opposed, you can notice the throughput on the Stale-Cache-enabled eZ Publish instance has no correlation with the cache clearings, is rather constant compared to the non Stale Cache version, and rarely drowns under 60 requests/sec. Throughput is smoothened, greatly enhancing user experience. Plus, although not appearing on this graph, system resources are preserved !
Conclusion
The Stale Cache feature is part of the many low-level improvements brought by eZ Publish 4.1, which do not pop up at first glance, but greatly enhance User experience and dramatically reduce the pressure on the architecture. We do recommend you to enable this feature ( unless your servers run Windows with a PHP version <= 5.3 ) in order for your eZ Publish based application to benefit from this instant booster.
We are looking forward to hearing your feedback on this ( and your benchmark results ) !
Thanks for reading !
Authors
References