Reactive tree caching
Building on the features of the first XTML template engine, we parse markup into a tree of objects instantiated from classes defining the behavior of the various elements. To render the document to XHTML, we recursively traverse the tree and each object is asked to generate a string representation of itself.
<xtm:google-map address="1501 Kincaid St, Eugene, OR 97403" height="300" width="400" />For example is represented in PHP as something like this:
xtm_google_map Object ( [ns] => "xtm", [tag] => "google-map", [attribs] => Array ( [address] => "1501 Kincaid St, Eugene, OR 97403", [height] => 300, [width] => 400 ) // etc... )
And when the object renders itself, the script accesses the Google API to get the URL for the map image. This is outputted as an image tag in XHTML:
<img src="http://some.google.map?..." height="300px" width="400px" alt="1501 Kincaid St, Eugene, OR 97403" />This works pretty well but until recently it has had some limitations. PHP’s serialize/unserialize functions get slow with very large strings so requests to heavy pages where complex document trees needed to load weren’t as snappy as we would like. To overcome this problem our new template objects store local caches that flush when new content is added to them. The effectiveness of these local caches is monitored and used to optimized the document trees by storing inactive segments in separate cache sets. These segments are only loaded back into the active document tree when an element they contain is accessed.
Bearing in mind that the greatest strength of the system is the ability to efficiently output content that updates with varying frequency, I ran a quick performance comparison with some static markup from the Ticket Office home page. I used ab with 50 concurrent connections over 30 seconds against our development environment. The following results show a 53% improvement to requests per second over rebuilding the document every request and a 17% improvement over caching the full document tree:
No caching:
Time taken for tests: 30.34176 seconds Complete requests: 4814 Failed requests: 0 Write errors: 0 Total transferred: 33388958 bytes HTML transferred: 32218184 bytes Requests per second: 160.28 [#/sec] (mean) Time per request: 311.946 [ms] (mean) Time per request: 6.239 [ms] (mean, across all concurrent requests) Transfer rate: 1085.63 [Kbytes/sec] received
Simple caching:
Time taken for tests: 30.056 seconds Complete requests: 6219 Failed requests: 0 Write errors: 0 Total transferred: 43165699 bytes HTML transferred: 41649865 bytes Requests per second: 207.30 [#/sec] (mean) Time per request: 241.197 [ms] (mean) Time per request: 4.824 [ms] (mean, across all concurrent requests) Transfer rate: 1405.13 [Kbytes/sec] received
Optimized caching:
Time taken for tests: 30.14062 seconds Complete requests: 7324 Failed requests: 0 Write errors: 0 Total transferred: 50898857 bytes HTML transferred: 49111106 bytes Requests per second: 244.02 [#/sec] (mean) Time per request: 204.902 [ms] (mean) Time per request: 4.098 [ms] (mean, across all concurrent requests) Transfer rate: 1656.06 [Kbytes/sec] received
1 Comment › Leave yours
Leave a Reply
Contact Us
Search this Site
Archives
- October 2009 (1)
- September 2009 (2)
- August 2009 (2)
- June 2009 (1)
- May 2009 (1)
- March 2009 (2)
- February 2009 (3)
- January 2009 (5)
- December 2008 (1)
- November 2008 (2)
- October 2008 (3)
- September 2008 (4)
- August 2008 (4)








Cool!