Check caching for speed

Discussion corner for Developers of Serendipity.
Post Reply
nealk
Regular
Posts: 26
Joined: Sun Sep 20, 2009 1:09 am

Check caching for speed

Post by nealk »

I've noticed that two URLs on my blog comprise the majority of DB queries (> 90%). They are accesses to "/blog/" (and /blog/index.php without any "?" parameters), and accesses to my rss2 feed (that's the only RSS feed I enabled).

I just modified index.php to cache results for 5 minutes, just to make results faster. (This works on my system because I don't typically update entries faster than once a week, and one every 5 minutes is good enough for the seldom-changing content.)

This cheap change requires four steps:

1. Create a cache directory under your blog. I used mkdir 'blog/fastcache/'

2. Add in code that checks the cache for already generated content. If it is less than 5 minutes, then return the content. Otherwise, generate the output into a buffer. Put this at the start of index.php:

Code: Select all

  global $NAKCache;
  $NAKCache=false;
  if ($_SERVER['REQUEST_METHOD']=='GET')
    {
    if ($_SERVER['REQUEST_URI']=="/blog/index.php?/feeds/index.rss2") { $NAKCache="fastcache/feeds_index.rss2"; }
    elseif ($_SERVER['REQUEST_URI']=="/blog/index.php") { $NAKCache="fastcache/index.php"; }
    elseif ($_SERVER['REQUEST_URI']=="/blog/") { $NAKCache="fastcache/index.php"; }
    }
  if ($NAKCache) // If using hacked cache
    {
    if (is_file($NAKCache) && (time()-filemtime($NAKCache) < 5*60))
      {
      readfile($NAKCache);
      return;
      }
    ob_start();
    }
The "NAK" prefix are my initials. Feel free to change those variable names. Also, the 5 minute timeout (5*60) should probably be configurable.

3. At the end of index.php, add the closing/write-cache code:

Code: Select all

NAKexit:
  if ($NAKCache) // Save to hacked cache
    {
    $Out=ob_get_clean();
    if (substr_count($Out,"\n") > 20) { file_put_contents($NAKCache,$Out,LOCK_EX); }
    elseif (is_file($NAKCache)) { $Out = file_get_contents($NAKCache); }
    echo $Out;
    }
Yes: I use a goto tag...
Also, if the output is shorter than 20 lines, then I assume there was a bug somewhere. This won't cache bugs.

4. index.php has a couple of 'exit;' calls. That's bad because RSS code won't reach my cache write code. Change every 'exit;' to 'goto NAKexit;'.

That's it. This little code change dramatically sped up the server since it isn't doing a database query each time. And it will auto-refresh within 5 minutes.
onli
Regular
Posts: 2822
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Check caching for speed

Post by onli »

That is a nice idea. I tried a caching scheme before (to the db though, but that still should help), and Garvin had a powercache-branch. I really would like to have soemthing like that in s9y.
Don Chambers
Regular
Posts: 3652
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Re: Check caching for speed

Post by Don Chambers »

onli wrote:I really would like to have soemthing like that in s9y.
X2 !!!!!
=Don=
mattsches
Regular
Posts: 440
Joined: Sat Nov 05, 2005 9:35 pm
Location: Wiesbaden, Germany
Contact:

Re: Check caching for speed

Post by mattsches »

There are also some plugins which implement their own caching. Maybe we can think of a way to create a global cache class that can be utilized by the core as well as any plugin that wants to.

(Yes, index.php is quite a mess - and not easy to clean up :cry: )
nealk
Regular
Posts: 26
Joined: Sun Sep 20, 2009 1:09 am

Re: Check caching for speed

Post by nealk »

One more hack for my temp cache...

When a user post/edits an entry, the cache should be flushed.
File: include/functions_entries.inc.php
Function: serendipity_updertEntry
At the end (right before the final return), I added:

Code: Select all

    // NAKcache
    touch(S9Y_INCLUDE_PATH . "cache/flush"); // ensure rm -f works
    exec("rm -f " . S9Y_INCLUDE_PATH . "cache/*");
This way, any edits will flush the cache. (Without this, you have to wait 5 minutes for that spelling error to vanish.)
onli
Regular
Posts: 2822
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Check caching for speed

Post by onli »

Yes, that would be necessary. Good idea.

Do you maybe want to send something like that in a push-request, as a feature branch based on master? I can't promise we will merge it, and I think it should use something the cachesimple helper instead of doing the file management manually, but to be able to test it easily should certainly help with modifications like that.

I can imagine we could merge it as an option, not on by default. And maybe enhance it to cache forever till something changes on disk?
onli
Regular
Posts: 2822
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Check caching for speed

Post by onli »

I now tested this a bit more with a benchmark of the cache options we have. That benchmark was siege, s9y ran on localhost on the same PC (so not too professional). My PC has a SSD and should be more powerful than a shared hoster, but less so than a professional server. 15 entries on the frontpage, fresh s9y with sqlite. This is the result: https://docs.google.com/spreadsheets/d/ ... sp=sharing

Here is the chart extracted:
Image

My conclusion is that nealks approach is great. By circumventing s9y completely, the cpu stays without load even at the highest user level I can benchmark with siege. The response time is immediately.

When not having any cache enabled, s9y can hold up on my pc only till 200 concurrent users. At 300, there is a massive spike in response times. No failed transactions yet, which is good. But in total not good.

The entryproperties plugin helps quite a bit, but the load is still heavy

My printEntries-cache might be a good compromise. Not as nice results as the total cache, but nearer to that than to the entryporperties cache. What is missing in the chart and data is the cpu load, and that is still signifcant higher than with nealks apprach.


Let's discuss that. Maybe you want to do your own tests as well? I'd like to pick one of the two approaches and add them to github, either as feature branch or to master, so we can start implementing it properly:
  • The printEntries-cache needs further cache-invaldiation points, and we maybe want to use something other than cache_lite.
  • nealks code is just a prototype and needs a complete and proper implementation, and maybe cache invalidation points as well? That proper implementation could mean that we lose some of its advantage, since we need to get the proper paths, which means autodetection and database hits (for the config).
It might be even possible to have the two caches: One as an internal faster cached codepath, the other as an optional interval cache, converting s9y for that interval in something like a static webpage.
onli
Regular
Posts: 2822
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Check caching for speed

Post by onli »

Github-Issue, for the printEntries Cache I commited since: https://github.com/s9y/Serendipity/issues/345
onli
Regular
Posts: 2822
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Check caching for speed

Post by onli »

A gem in the index.php:

Code: Select all

if (isset($serendipity['pregenerate']) && $serendipity['pregenerate']) {
    $fp = fopen($serendipity['serendipityPath'] . PATH_ARCHIVES.'/' . $id, 'w');
    fwrite($fp, $data);
    fclose($fp);
}
If I see that right, there is already some code in the core to cache entries, to have them as a textfile under /archive and serve them via s9y without hitting the database. It seems broken though, as I can only find the code that would write those files, but none that would read it. Maybe that was not meant as a cache, but as a textfile mirror? Or it was how the entryproperties-cache worked once? Garvin?
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Re: Check caching for speed

Post by garvinhicking »

Hey,

this is code from Serendipity 0.3 or 0.4 I think, that never was used and it was added before I joined the project, and I never analyzed what or if good it could do.

Best regards,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
onli
Regular
Posts: 2822
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: Check caching for speed

Post by onli »

Thanks for the response Garvin. I removed it in https://github.com/s9y/Serendipity/comm ... 8dd8458d34.
Post Reply