Another Christmas gift: record cache improvements, caching engines, etc

Another Christmas gift: record cache improvements, caching engines, etc

by Martín Langhoff -
Number of replies: 7
A couple of days ago, one of the core moodle developers checked into CVS a really nice enhancement as a Christmas gift. (Does anyone know what it was and who did it? Really cool stuff, let me tell you! wink ) So I felt I could do a bit of my own here...

In HEAD, landing right now, are some interesting performance enhancements around database access. Sam Marshal had checked in a really neat bit of caching code for the simple get_record() call that improves performance significantly in some pages such as course/view.php . So I went back to some old plans I had to do something similar, and worked on top of Sam's code. So what we have right now is...

- a new $MCACHE global object that refers to an in-memory cache (either memcached or eaccelerator/turckmmcache) that can add(), set(), delete(), get(). Only the memcached implementation is complete. You will need a running memcached and the memcache PECL libraries (apt-get install php5-memcached). Enable setting $CFG->memcached=true; $CFG->memcachedhosts='localhost';. The idea is to use $MCACHE also for things like text filters.

- Sam's code is abstracted into a series of functions called rcache_get(), rcache_set(), etc. So get_record() and friends are using them. If $CFG->rcache is set to 'internal' then Sam's per-process cache is used. If set to anything else (like 'memcached') then $MCACHE will be used. If unset or empty, no record cache is used.

One of the hardest things to deal with in a web cache is the case of thundering herds -- when there are many clients asking for the same thing in parallel, and you don't even get a chance to cache it before the server load goes through the roof. In such cases, the trick is to force a bit of serialisation in the identical requests. To deal with that scenario gracefully we have rcache_getforfill() which was inspired by an email by Linus Torvalds on how to do backend caching for web apps.

A nice view of the patches:
http://git.catalyst.net.nz/gitweb?p=moodle-r2.git;a=log;h=mdl18-rcache

Discussion of the read-for-fill operation that memcached is missing .. and that I've implemented as getforfill() on top of the memcached API wink
http://marc.theaimsgroup.com/?l=git&m=116562052506776&w=2

From my limited profiling so far, there is an overhead in the marshalling/unmarshalling of the record object. So in really small installs, you don't want to use any of this, except perhaps the 'internal' rcache. For any of this code to improve performance you have to be seeing reasonably high concurrency and the database server working hard. In that case...

- if you have a single maching running apache/php, use the (still incomplete) eaccelerator/turckmmcache option. Memcached will work but will probably be slower due to http connection latency.

- For load-balanced servers you cannot use eaccelerator/turckmmcache safely; use memcached instead. You can have a single memcached server, or a pool of them. Just make sure that all the Moodle installs are seeing all the memcached servers so the key distribution scheme works correctly.

Phew. Did any of that make sense? smile In any case, there is still work to do:

- implement eaccelerator/turckmmcache properly
- perhaps move the getforfill logic into the code implementing the MCACHE object
- some more profiling
- make all these options configurable via GUI and migrate settings from $CFG->enablerecordcache
- reimplement limits to in-memory cache
- document in docs.moodle.org

~ Merry xmas!
Average of ratings: Useful (2)
In reply to Martín Langhoff

Re: Another Christmas gift: record cache improvements, caching engines, etc

by Martín Langhoff -
All in HEAD now, with an eaccelerator/turckmmcache implementation.

For an easy view of the patchseries, see http://git.catalyst.net.nz/gitweb?p=moodle-r2.git;a=log;h=mdl18-rcache

To test eaccelerator, make sure you have eaccelerator or turckmmcache installed, configured and with the shmem keys option enabled at compile time, and enabled in php.ini too.

in your config.php, set

// send debugging info to apache's errorlog
$CFG->debug=0; // set to 34815 if something isn't working
$CFG->debugdisplay=0;
define('MDL_PERF' , true);
define('MDL_PERFDB' , true);
define('MDL_PERFTOLOG' , true);

// enable rcache
$CFG->rcache=true;
// false disables all rcache
// true will try to use eaccel or memcached if setup
// 'internal' will use sam's per-process cache
$CFG->rcachettl=3;

// which MCACHE to use?
$CFG->eaccelerator=true;
// $CFG->memcached=true;
// $CFG->memcachedpconn=true;
// $CFG->memcachedhosts='127.0.0.1'; // comma separated list

and now you can hit your Moodle installation hard, and look at apache's error log. It will be reporting cache hits/misses. On a single-apache setup, eaccelerator is faster than memcached.

To test memcached, you need the memcached daemon running, and the PECL memcached extension installed and enabled. Use the same config as above, but with:

// which MCACHE to use?
// $CFG->eaccelerator=true;
$CFG->memcached=true;
$CFG->memcachedpconn=false; // true is faster, but the PECL
// extension is buggy and will segfault if the pconnection
// goes away
$CFG->memcachedhosts='127.0.0.1'; // comma separated list

All we are missing is the UI and the upgrade from enablerecordcache. Yay!
Average of ratings: Useful (1)
In reply to Martín Langhoff

Re: Another Christmas gift: record cache improvements, caching engines, etc

by Martín Langhoff -
Anyone up for documenting this in the wiki? wink
In reply to Martín Langhoff

record cache improvements -- anyone tried them?

by Martín Langhoff -
Hey! Has anyone tested/tried/benchmarked the changes with heavy courses? I'm interested to hear more about this... wink

In any case, Sam's filed a bug 'cause I've been slack and didn't update the config stuff. So fixing it now...!

http://tracker.moodle.org/browse/MDL-8163
In reply to Martín Langhoff

Re: record cache improvements -- configurable now

by Martín Langhoff -
Done! Get the latest HEAD and take a look at the performance options under admin. wide eyes
In reply to Martín Langhoff

Re: record cache improvements -- anyone tried them?

by sam marshall -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers
We are running this (set to the internal per-query one only, and with code from before you added the config options) and haven't noticed whether performance is the same, better, or worse than with the old record cache. smile But it doesn't seem to have critically broken anything or made an enormous difference in performance.

We do see a slight increase in memory usage when running pages which use a great many queries, as would be expected.

For example when logging in as a user with admin permissions (~9,000 queries) RAM usage is 10.5MB to render a test course page. When rcache is turned off, logging in to the same page takes only 3.8MB.

For normal pages the memory usage is no problem, as expected from investigation when the first version of this feature was added. Rendering the page after login takes 170 queries with rcache off, 136 with rcache on, and about 2.6MB either way.

I don't think we are using one of the supported php accelerators, so we can't try the persistent cache.

This is running on our test server now (so being tested, supposedly) and will be live to students in about a week - yes, we're running pre-beta code, again! Yay! Sigh.

--sam
In reply to sam marshall

Re: record cache improvements -- anyone tried them?

by Martín Langhoff -
If your prod environment is using multiple webservers, try memcached -- it'll make things a lot easier on Pg.
Average of ratings: Useful (1)