From 252ef37028af515326bf281bf40ad80792540a2d Mon Sep 17 00:00:00 2001 From: Andrew Garrett Date: Mon, 9 Feb 2009 23:18:37 +0000 Subject: [PATCH] Apply changes made live on Wikimedia cluster related to preprocessor caching to subversion. Patch worked on by Tim Starling and myself. Changes from the original patch (r46936): * Add versioning to the cache, so the cache can be purged. * Only cache preprocessor output for input of over a certain amount (default of 1000 bytes). --- includes/DefaultSettings.php | 5 +++ includes/parser/Preprocessor_DOM.php | 45 ++++++++++++++++++++------- includes/parser/Preprocessor_Hash.php | 43 +++++++++++++++++++------ 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 949fd819bd..8171586771 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -3708,3 +3708,8 @@ $wgEnforceHtmlIds = true; * false = use Go button & Advanced search link */ $wgUseTwoButtonsSearchForm = true; + +/** + * Preprocessor caching threshold + */ +$wgPreprocessorCacheThreshold = 1000; \ No newline at end of file diff --git a/includes/parser/Preprocessor_DOM.php b/includes/parser/Preprocessor_DOM.php index 66b5e1d3e3..bd33c10249 100644 --- a/includes/parser/Preprocessor_DOM.php +++ b/includes/parser/Preprocessor_DOM.php @@ -6,6 +6,8 @@ class Preprocessor_DOM implements Preprocessor { var $parser, $memoryLimit; + const CACHE_VERSION = 1; + function __construct( $parser ) { $this->parser = $parser; $mem = ini_get( 'memory_limit' ); @@ -63,19 +65,37 @@ class Preprocessor_DOM implements Preprocessor { */ function preprocessToObj( $text, $flags = 0 ) { wfProfileIn( __METHOD__ ); + global $wgMemc, $wgPreprocessorCacheThreshold; - global $wgMemc; - $cacheKey = wfMemcKey( 'preprocess-xml', md5($text), $flags ); - - if ( $xml = $wgMemc->get( $cacheKey ) ) { - // From the cache - wfDebugLog( "Preprocessor", "Loaded preprocessor XML from memcached (key $cacheKey)" ); - } else { - $xml = $this->preprocessToXml( $text, $flags ); - $wgMemc->set( $cacheKey, $xml, 86400 ); - wfDebugLog( "Preprocessor", "Saved preprocessor XML to memcached (key $cacheKey)" ); + $xml = false; + $cacheable = strlen( $text ) > $wgPreprocessorCacheThreshold; + if ( $cacheable ) { + wfProfileIn( __METHOD__.'-cacheable' ); + + $cacheKey = wfMemcKey( 'preprocess-xml', md5($text), $flags ); + $cacheValue = $wgMemc->get( $cacheKey ); + if ( $cacheValue ) { + $version = substr( $cacheValue, 0, 8 ); + if ( intval( $version ) == self::CACHE_VERSION ) { + $xml = substr( $cacheValue, 8 ); + // From the cache + wfDebugLog( "Preprocessor", "Loaded preprocessor XML from memcached (key $cacheKey)" ); + } + } + } + if ( $xml === false ) { + if ( $cacheable ) { + wfProfileIn( __METHOD__.'-cache-miss' ); + $xml = $this->preprocessToXml( $text, $flags ); + $cacheValue = sprintf( "%08d", self::CACHE_VERSION ) . $xml; + $wgMemc->set( $cacheKey, $cacheValue, 86400 ); + wfProfileOut( __METHOD__.'-cache-miss' ); + wfDebugLog( "Preprocessor", "Saved preprocessor XML to memcached (key $cacheKey)" ); + } else { + $xml = $this->preprocessToXml( $text, $flags ); + } + } - wfProfileIn( __METHOD__.'-loadXML' ); $dom = new DOMDocument; wfSuppressWarnings(); @@ -91,6 +111,9 @@ class Preprocessor_DOM implements Preprocessor { } $obj = new PPNode_DOM( $dom->documentElement ); wfProfileOut( __METHOD__.'-loadXML' ); + if ( $cacheable ) { + wfProfileOut( __METHOD__.'-cacheable' ); + } wfProfileOut( __METHOD__ ); return $obj; } diff --git a/includes/parser/Preprocessor_Hash.php b/includes/parser/Preprocessor_Hash.php index 0bebdb7f24..f46ee40ce9 100644 --- a/includes/parser/Preprocessor_Hash.php +++ b/includes/parser/Preprocessor_Hash.php @@ -8,6 +8,8 @@ */ class Preprocessor_Hash implements Preprocessor { var $parser; + + const CACHE_VERSION = 1; function __construct( $parser ) { $this->parser = $parser; @@ -45,14 +47,30 @@ class Preprocessor_Hash implements Preprocessor { */ function preprocessToObj( $text, $flags = 0 ) { wfProfileIn( __METHOD__ ); + + + // Check cache. + global $wgMemc, $wgPreprocessorCacheThreshold; - global $wgMemc; - $cacheKey = wfMemckey( 'preprocessor-hash', md5( $text ), $flags ); - - if ( $obj = $wgMemc->get( $cacheKey ) ) { - wfDebugLog( "Preprocessor", "Got preprocessor_hash output from cache" ); - wfProfileOut( __METHOD__ ); - return $obj; + $cacheable = strlen( $text ) > $wgPreprocessorCacheThreshold; + if ( $cacheable ) { + wfProfileIn( __METHOD__.'-cacheable' ); + + $cacheKey = wfMemcKey( 'preprocess-hash', md5($text), $flags ); + $cacheValue = $wgMemc->get( $cacheKey ); + if ( $cacheValue ) { + $version = substr( $cacheValue, 0, 8 ); + if ( intval( $version ) == self::CACHE_VERSION ) { + $hash = unserialize( substr( $cacheValue, 8 ) ); + // From the cache + wfDebugLog( "Preprocessor", + "Loaded preprocessor hash from memcached (key $cacheKey)" ); + wfProfileOut( __METHOD__.'-cacheable' ); + wfProfileOut( __METHOD__ ); + return $hash; + } + } + wfProfileIn( __METHOD__.'-cache-miss' ); } $rules = array( @@ -626,10 +644,17 @@ class Preprocessor_Hash implements Preprocessor { $rootNode = new PPNode_Hash_Tree( 'root' ); $rootNode->firstChild = $stack->rootAccum->firstNode; $rootNode->lastChild = $stack->rootAccum->lastNode; - wfProfileOut( __METHOD__ ); - $wgMemc->set( $cacheKey, $rootNode, 86400 ); + // Cache + if ($cacheable) { + $cacheValue = sprintf( "%08d", self::CACHE_VERSION ) . serialize( $rootNode );; + $wgMemc->set( $cacheKey, $cacheValue, 86400 ); + wfProfileOut( __METHOD__.'-cache-miss' ); + wfProfileOut( __METHOD__.'-cacheable' ); + wfDebugLog( "Preprocessor", "Saved preprocessor Hash to memcached (key $cacheKey)" ); + } + wfProfileOut( __METHOD__ ); return $rootNode; } } -- 2.20.1