Merge "Optimise MessageCache::isMainCacheable() for the single-message case"

This commit is contained in:
jenkins-bot 2021-05-15 02:52:30 +00:00 committed by Gerrit Code Review
commit dba72b74c3
2 changed files with 60 additions and 16 deletions

View file

@ -72,11 +72,11 @@ class MessageCache implements LoggerAwareInterface {
protected $cache;
/**
* Map of (lowercase message key => index) for all software defined messages
* Map of (lowercase message key => unused) for all software defined messages
*
* @var array
*/
protected $overridable;
private $systemMessageNames;
/**
* @var bool[] Map of (language code => boolean)
@ -288,9 +288,6 @@ class MessageCache implements LoggerAwareInterface {
return true;
}
$this->overridable =
array_flip( $this->localisationCache->getSubitemList( $code, 'messages' ) );
# 8 lines of code just to say (once) that message cache is disabled
if ( $this->mDisable ) {
static $shownDisabled = false;
@ -508,10 +505,6 @@ class MessageCache implements LoggerAwareInterface {
}
}
// Get the list of software-defined messages in core/extensions
$overridable =
array_flip( $this->localisationCache->getSubitemList( $wgLanguageCode, 'messages' ) );
// Common conditions
$conds = [
'page_is_redirect' => 0,
@ -537,7 +530,8 @@ class MessageCache implements LoggerAwareInterface {
);
foreach ( $res as $row ) {
// Include entries/stubs for all keys in $mostused in adaptive mode
if ( $wgAdaptiveMessageCache || $this->isMainCacheable( $row->page_title, $overridable ) ) {
if ( $wgAdaptiveMessageCache || $this->isMainCacheable( $row->page_title )
) {
$cache[$row->page_title] = '!TOO BIG';
}
// At least include revision ID so page changes are reflected in the hash
@ -582,7 +576,8 @@ class MessageCache implements LoggerAwareInterface {
$revisions = $result->isOK() ? $result->getValue() : [];
foreach ( $res as $row ) {
// Include entries/stubs for all keys in $mostused in adaptive mode
if ( $wgAdaptiveMessageCache || $this->isMainCacheable( $row->page_title, $overridable ) ) {
if ( $wgAdaptiveMessageCache || $this->isMainCacheable( $row->page_title )
) {
try {
$rev = $revisions[$row->rev_id] ?? null;
$content = $rev ? $rev->getContent( SlotRecord::MAIN ) : null;
@ -638,17 +633,39 @@ class MessageCache implements LoggerAwareInterface {
}
/**
* Can the given DB key be added to the main cache blob? To reduce the
* impact of abuse of the MediaWiki namespace by {{int:}} and CentralNotice,
* this is only true if the page overrides a predefined message.
*
* @param string $name Message name (possibly with /code suffix)
* @param array $overridable Map of (key => unused) for software-defined messages
* @param string|null $code The language code. If this is null, message
* presence will be bulk loaded for the content language. Otherwise,
* presence will be detected by loading the specified message.
* @return bool
*/
private function isMainCacheable( $name, array $overridable ) {
private function isMainCacheable( $name, $code = null ) {
global $wgLanguageCode;
// Convert first letter to lowercase, and strip /code suffix
$name = $this->contLang->lcfirst( $name );
$msg = preg_replace( '/\/[a-z0-9-]{2,}$/', '', $name );
// Include common conversion table pages. This also avoids problems with
// Installer::parse() bailing out due to disallowed DB queries (T207979).
return ( isset( $overridable[$msg] ) || strpos( $name, 'conversiontable/' ) === 0 );
if ( strpos( $name, 'conversiontable/' ) === 0 ) {
return true;
}
$msg = preg_replace( '/\/[a-z0-9-]{2,}$/', '', $name );
if ( $code === null ) {
// Bulk load
if ( $this->systemMessageNames === null ) {
$this->systemMessageNames = array_flip(
$this->localisationCache->getSubitemList( $wgLanguageCode, 'messages' ) );
}
return isset( $this->systemMessageNames[$msg] );
} else {
// Use individual subitem
return $this->localisationCache->getSubitem( $code, 'messages', $msg ) !== null;
}
}
/**
@ -1118,7 +1135,7 @@ class MessageCache implements LoggerAwareInterface {
);
} else {
// Message page either does not exist or does not override a software message
if ( !$this->isMainCacheable( $title, $this->overridable ) ) {
if ( !$this->isMainCacheable( $title, $code ) ) {
// Message page does not override any software-defined message. A custom
// message might be defined to have content or settings specific to the wiki.
// Load the message page, utilizing the individual message cache as needed.

View file

@ -281,4 +281,31 @@ class MessageCacheTest extends MediaWikiLangTestCase {
$this->assertSame( ' ' . 'Test drei', $cache[$key] );
}
/**
* @dataProvider provideIsMainCacheable
* @param string|null $code The language code
* @param string $message The message key
* @param bool $expected
*/
public function testIsMainCacheable( $code, $message, $expected ) {
$messageCache = TestingAccessWrapper::newFromObject(
MediaWikiServices::getInstance()->getMessageCache() );
$this->assertSame( $expected, $messageCache->isMainCacheable( $message, $code ) );
}
public function provideIsMainCacheable() {
$cases = [
// $message $expected
[ 'allpages', true ],
[ 'Allpages', true ],
[ 'Allpages/bat', true ],
[ 'Conversiontable/zh-tw', true ],
[ 'My_special_message', false ],
];
foreach ( [ null, 'en', 'fr' ] as $code ) {
foreach ( $cases as $case ) {
yield array_merge( [ $code ], $case );
}
}
}
}