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
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?
- 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!