r60715 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r60714‎ | r60715 | r60716 >
Date:05:48, 6 January 2010
Author:tstarling
Status:deferred
Tags:
Comment:
Made Special:Allmessages many times faster for a typical installation, by taking advantage of the message name list available from LocalisationCache to avoid unnecessary message loads. Now it only loads messages that are on the current page being displayed.
Modified paths:
  • /trunk/phase3/includes/LocalisationCache.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialAllmessages.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/LocalisationCache.php
@@ -233,6 +233,28 @@
234234 }
235235
236236 /**
 237+ * Get the list of subitem keys for a given item.
 238+ *
 239+ * This is faster than array_keys($lc->getItem(...)) for the items listed in
 240+ * self::$splitKeys.
 241+ *
 242+ * Will return null if the item is not found, or false if the item is not an
 243+ * array.
 244+ */
 245+ public function getSubitemList( $code, $key ) {
 246+ if ( in_array( $key, self::$splitKeys ) ) {
 247+ return $this->getSubitem( $code, 'list', $key );
 248+ } else {
 249+ $item = $this->getItem( $code, $key );
 250+ if ( is_array( $item ) ) {
 251+ return array_keys( $item );
 252+ } else {
 253+ return false;
 254+ }
 255+ }
 256+ }
 257+
 258+ /**
237259 * Load an item into the cache.
238260 */
239261 protected function loadItem( $code, $key ) {
Index: trunk/phase3/includes/specials/SpecialAllmessages.php
@@ -126,8 +126,6 @@
127127 */
128128 class AllmessagesTablePager extends TablePager {
129129
130 - var $messages = null;
131 - var $talkPages = null;
132130 public $mLimitsShown;
133131
134132 function __construct( $page, $conds, $langObj = null ) {
@@ -152,7 +150,7 @@
153151 if( $wgRequest->getVal( 'filter', 'all' ) === 'all' ){
154152 $this->custom = null; // So won't match in either case
155153 } else {
156 - $this->custom = $wgRequest->getVal( 'filter' ) == 'unmodified' ? 1 : 0;
 154+ $this->custom = ($wgRequest->getVal( 'filter' ) == 'unmodified');
157155 }
158156
159157 $prefix = $wgLang->ucfirst( $wgRequest->getVal( 'prefix', '' ) );
@@ -173,46 +171,29 @@
174172 }
175173 }
176174
177 - function getAllMessages( $desc ){
178 - wfProfileIn( __METHOD__ . '-cache' );
179 -
180 - # Make sure all extension messages are available
181 - global $wgMessageCache;
182 - $wgMessageCache->loadAllMessages( 'en' );
183 - $sortedArray = Language::getMessagesFor( 'en' );
184 - if( $desc ){
185 - krsort( $sortedArray );
 175+ function getAllMessages( $descending ) {
 176+ wfProfileIn( __METHOD__ );
 177+ $messageNames = Language::getLocalisationCache()->getSubitemList( 'en', 'messages' );
 178+ if( $descending ){
 179+ krsort( $messageNames );
186180 } else {
187 - ksort( $sortedArray );
 181+ ksort( $messageNames );
188182 }
189183
190 - $this->messages = array();
191 - foreach( $sortedArray as $key => $value ) {
192 - // All messages start with lowercase, but wikis might have both
193 - // upper and lowercase MediaWiki: pages if $wgCapitalLinks=false.
194 - $ukey = $this->lang->ucfirst( $key );
 184+ // Normalise message names so they look like page titles
 185+ $messageNames = array_map( array( $this->lang, 'ucfirst' ), $messageNames );
 186+ wfProfileIn( __METHOD__ );
195187
196 - // The value without any overrides from the MediaWiki: namespace
197 - $this->messages[$ukey]['default'] = wfMsgGetKey( $key, /*useDB*/false, $this->langcode, false );
198 -
199 - // The message that's actually used by the site
200 - $this->messages[$ukey]['actual'] = wfMsgGetKey( $key, /*useDB*/true, $this->langcode, false );
201 -
202 - $this->messages[$ukey]['customised'] = 0; //for now
203 -
204 - $sortedArray[$key] = null; // trade bytes from $sortedArray to this
205 - }
206 -
207 - wfProfileOut( __METHOD__ . '-cache' );
208 -
209 - return true;
 188+ return $messageNames;
210189 }
211190
212 - # We only need a list of which messages have *been* customised;
213 - # their content is already in the message cache.
214 - function markCustomisedMessages(){
215 - $this->talkPages = array();
216 -
 191+ /**
 192+ * Determine which of the MediaWiki and MediaWiki_talk namespace pages exist.
 193+ * Returns array( 'pages' => ..., 'talks' => ... ), where the subarrays have
 194+ * an entry for each existing page, with the key being the message name and
 195+ * value arbitrary.
 196+ */
 197+ function getCustomisedStatuses( $messageNames ) {
217198 wfProfileIn( __METHOD__ . '-db' );
218199
219200 $dbr = wfGetDB( DB_SLAVE );
@@ -222,56 +203,61 @@
223204 __METHOD__,
224205 array( 'USE INDEX' => 'name_title' )
225206 );
 207+ $xNames = array_flip( $messageNames );
226208
 209+ $pageFlags = $talkFlags = array();
 210+
227211 while( $s = $dbr->fetchObject( $res ) ) {
228 - if( $s->page_namespace == NS_MEDIAWIKI ){
229 - if( $this->foreign ){
 212+ if( $s->page_namespace == NS_MEDIAWIKI ) {
 213+ if( $this->foreign ) {
230214 $title = explode( '/', $s->page_title );
231 - if( count( $title ) === 2 && $this->langcode == $title[1] && array_key_exists( $title[0], $this->messages ) ){
232 - $this->messages["{$title[0]}"]['customised'] = 1;
 215+ if( count( $title ) === 2 && $this->langcode == $title[1]
 216+ && isset( $xNames[$title[0]] ) )
 217+ {
 218+ $pageFlags["{$title[0]}"] = true;
233219 }
234 - } else if( array_key_exists( $s->page_title, $this->messages ) ){
235 - $this->messages[$s->page_title]['customised'] = 1;
 220+ } elseif( isset( $xNames[$s->page_title] ) ) {
 221+ $pageFlags[$s->page_title] = true;
236222 }
237223 } else if( $s->page_namespace == NS_MEDIAWIKI_TALK ){
238 - $this->talkPages[$s->page_title] = 1;
 224+ $talkFlags[$s->page_title] = true;
239225 }
240226 }
241227 $dbr->freeResult( $res );
242228
243229 wfProfileOut( __METHOD__ . '-db' );
244230
245 - return true;
 231+ return array( 'pages' => $pageFlags, 'talks' => $talkFlags );
246232 }
247233
248234 /* This function normally does a database query to get the results; we need
249235 * to make a pretend result using a FakeResultWrapper.
250236 */
251 - function reallyDoQuery( $offset, $limit, $descending ){
252 - $mResult = new FakeResultWrapper( array() );
 237+ function reallyDoQuery( $offset, $limit, $descending ) {
 238+ $result = new FakeResultWrapper( array() );
253239
254 - if( !$this->messages ) $this->getAllMessages( $descending );
255 - if( $this->talkPages === null ) $this->markCustomisedMessages();
 240+ $messageNames = $this->getAllMessages( $descending );
 241+ $statuses = $this->getCustomisedStatuses( $messageNames );
256242
257243 $count = 0;
258 - foreach( $this->messages as $key => $value ){
259 - if( $value['customised'] !== $this->custom &&
 244+ foreach( $messageNames as $key ) {
 245+ $customised = isset( $statuses['pages'][$key] );
 246+ if( $customised !== $this->custom &&
260247 ( $descending && ( $key < $offset || !$offset ) || !$descending && $key > $offset ) &&
261248 ( ( $this->prefix && preg_match( $this->prefix, $key ) ) || $this->prefix === false )
262249 ){
263 - $mResult->result[] = array(
 250+ $result->result[] = array(
264251 'am_title' => $key,
265 - 'am_actual' => $value['actual'],
266 - 'am_default' => $value['default'],
267 - 'am_customised' => $value['customised'],
 252+ 'am_actual' => wfMsgGetKey( $key, /*useDB*/true, $this->langcode, false ),
 253+ 'am_default' => wfMsgGetKey( $key, /*useDB*/false, $this->langcode, false ),
 254+ 'am_customised' => $customised,
 255+ 'am_talk_exists' => isset( $statuses['talks'][$key] )
268256 );
269 - unset( $this->messages[$key] ); // save a few bytes
270257 $count++;
271258 }
272259 if( $count == $limit ) break;
273260 }
274 - unset( $this->messages ); // no longer needed, free up some memory
275 - return $mResult;
 261+ return $result;
276262 }
277263
278264 function getStartBody() {
@@ -311,7 +297,7 @@
312298 array( 'broken' )
313299 );
314300 }
315 - if( array_key_exists( $talk->getDBkey() , $this->talkPages ) ) {
 301+ if ( $this->mCurrentRow->am_talk_exists ) {
316302 $talk = $this->mSkin->linkKnown( $talk , $this->talk );
317303 } else {
318304 $talk = $this->mSkin->link(

Status & tagging log