Request-local caching of revision text
authorOri Livneh <ori@wikimedia.org>
Wed, 23 Mar 2016 00:21:48 +0000 (17:21 -0700)
committerOri Livneh <ori@wikimedia.org>
Wed, 23 Mar 2016 05:28:31 +0000 (22:28 -0700)
It's not uncommon for the revision text of a Scribunto module to be retrieved
half a dozen times or more in the course of a single request. Caching them in
APC is a non-starter, because there is no practical way to determine which keys
are hot, and storing everything in APC is not viable. Request-local caching
gives us much of the benefit with no negative consequences apart from a nominal
increase to memory usage.

Use a MapCacheLRU to hold cache items so we can limit the size of the cache to
10 items, to prevent uncontrolled memory growth for long-running scripts.

Change-Id: I77575d6d0ea2d06fc6c93f664c5407641aab88d9

includes/Revision.php

index 3db3744..b7bb346 100644 (file)
@@ -1549,14 +1549,24 @@ class Revision implements IDBAccessObject {
        protected function loadText() {
                // Caching may be beneficial for massive use of external storage
                global $wgRevisionCacheExpiry;
+               static $processCache = null;
+
+               if ( !$processCache ) {
+                       $processCache = new MapCacheLRU( 10 );
+               }
 
                $cache = ObjectCache::getMainWANInstance();
                $textId = $this->getTextId();
                $key = wfMemcKey( 'revisiontext', 'textid', $textId );
+
                if ( $wgRevisionCacheExpiry ) {
+                       if ( $processCache->has( $key ) ) {
+                               return $processCache->get( $key );
+                       }
                        $text = $cache->get( $key );
                        if ( is_string( $text ) ) {
                                wfDebug( __METHOD__ . ": got id $textId from cache\n" );
+                               $processCache->set( $key, $text );
                                return $text;
                        }
                }
@@ -1601,6 +1611,7 @@ class Revision implements IDBAccessObject {
 
                # No negative caching -- negative hits on text rows may be due to corrupted slave servers
                if ( $wgRevisionCacheExpiry && $text !== false ) {
+                       $processCache->set( $key, $text );
                        $cache->set( $key, $text, $wgRevisionCacheExpiry );
                }