RecentChanges: Add process caching to RecentChanges UserLinks and Tags parsing
Rendering UserLinks or Tags requires parsing, which when run on thousands of records, adds up to a significant amount of processing time. More often than not, this can be optimized by storing already visited tags or user links as those "renders" will not change for the single request run and are repeated constantly on the list. Bug: T341319 Change-Id: I91588aebae7e49e3d3cb77702cf28677b4a14c8d
This commit is contained in:
parent
709a5cce79
commit
a468534689
2 changed files with 77 additions and 22 deletions
|
|
@ -77,6 +77,11 @@ class ChangesList extends ContextSource {
|
||||||
*/
|
*/
|
||||||
protected $filterGroups;
|
protected $filterGroups;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MapCacheLRU
|
||||||
|
*/
|
||||||
|
protected $tagsCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param IContextSource $context
|
* @param IContextSource $context
|
||||||
* @param ChangesListFilterGroup[] $filterGroups Array of ChangesListFilterGroup objects (currently optional)
|
* @param ChangesListFilterGroup[] $filterGroups Array of ChangesListFilterGroup objects (currently optional)
|
||||||
|
|
@ -90,6 +95,7 @@ class ChangesList extends ContextSource {
|
||||||
$services = MediaWikiServices::getInstance();
|
$services = MediaWikiServices::getInstance();
|
||||||
$this->linkRenderer = $services->getLinkRenderer();
|
$this->linkRenderer = $services->getLinkRenderer();
|
||||||
$this->commentFormatter = $services->getRowCommentFormatter();
|
$this->commentFormatter = $services->getRowCommentFormatter();
|
||||||
|
$this->tagsCache = new MapCacheLRU( 50 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -903,10 +909,23 @@ class ChangesList extends ContextSource {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ $tagSummary, $newClasses ] = ChangeTags::formatSummaryRow(
|
/**
|
||||||
$rc->mAttribs['ts_tags'],
|
* Tags are repeated for a lot of the records, so during single run of RecentChanges, we
|
||||||
'changeslist',
|
* should cache those that were already processed as doing that for each record takes
|
||||||
$this->getContext()
|
* significant amount of time.
|
||||||
|
*/
|
||||||
|
[ $tagSummary, $newClasses ] = $this->tagsCache->getWithSetCallback(
|
||||||
|
sprintf(
|
||||||
|
'%s:%s:%s',
|
||||||
|
$rc->mAttribs['ts_tags'],
|
||||||
|
$this->getUser()->getName(),
|
||||||
|
$this->getLanguage()->getCode()
|
||||||
|
),
|
||||||
|
fn() => ChangeTags::formatSummaryRow(
|
||||||
|
$rc->mAttribs['ts_tags'],
|
||||||
|
'changeslist',
|
||||||
|
$this->getContext()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
$classes = array_merge( $classes, $newClasses );
|
$classes = array_merge( $classes, $newClasses );
|
||||||
$s .= ' ' . $tagSummary;
|
$s .= ' ' . $tagSummary;
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,16 @@ class RCCacheEntryFactory {
|
||||||
*/
|
*/
|
||||||
private $linkRenderer;
|
private $linkRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MapCacheLRU
|
||||||
|
*/
|
||||||
|
private MapCacheLRU $userLinks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MapCacheLRU
|
||||||
|
*/
|
||||||
|
private MapCacheLRU $userTalkLinks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param IContextSource $context
|
* @param IContextSource $context
|
||||||
* @param string[] $messages
|
* @param string[] $messages
|
||||||
|
|
@ -50,6 +60,8 @@ class RCCacheEntryFactory {
|
||||||
$this->context = $context;
|
$this->context = $context;
|
||||||
$this->messages = $messages;
|
$this->messages = $messages;
|
||||||
$this->linkRenderer = $linkRenderer;
|
$this->linkRenderer = $linkRenderer;
|
||||||
|
$this->userLinks = new MapCacheLRU( 50 );
|
||||||
|
$this->userTalkLinks = new MapCacheLRU( 50 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -85,17 +97,31 @@ class RCCacheEntryFactory {
|
||||||
$cacheEntry->userlink = $this->getUserLink( $cacheEntry );
|
$cacheEntry->userlink = $this->getUserLink( $cacheEntry );
|
||||||
|
|
||||||
if ( !ChangesList::isDeleted( $cacheEntry, RevisionRecord::DELETED_USER ) ) {
|
if ( !ChangesList::isDeleted( $cacheEntry, RevisionRecord::DELETED_USER ) ) {
|
||||||
$cacheEntry->usertalklink = Linker::userToolLinks(
|
/**
|
||||||
$cacheEntry->mAttribs['rc_user'],
|
* userToolLinks requires a lot of parser work to process multiple links that are
|
||||||
$cacheEntry->mAttribs['rc_user_text'],
|
* rendered there, like contrib page, user talk etc. Often, active
|
||||||
// Should the contributions link be red if the user has no edits (using default)
|
* users will appear multiple times on same run of RecentChanges, and therefore it is
|
||||||
false,
|
* unnecessary to process it for each RC record separately.
|
||||||
// Customisation flags (using default 0)
|
*/
|
||||||
0,
|
$cacheEntry->usertalklink = $this->userTalkLinks->getWithSetCallback(
|
||||||
// User edit count (using default )
|
sprintf(
|
||||||
null,
|
'%s:%s:%s',
|
||||||
// do not wrap the message in parentheses
|
$cacheEntry->mAttribs['rc_user_text'],
|
||||||
false
|
$this->context->getUser()->getName(),
|
||||||
|
$this->context->getLanguage()->getCode()
|
||||||
|
),
|
||||||
|
fn() => Linker::userToolLinks(
|
||||||
|
$cacheEntry->mAttribs['rc_user'],
|
||||||
|
$cacheEntry->mAttribs['rc_user_text'],
|
||||||
|
// Should the contributions link be red if the user has no edits (using default)
|
||||||
|
false,
|
||||||
|
// Customisation flags (using default 0)
|
||||||
|
0,
|
||||||
|
// User edit count (using default )
|
||||||
|
null,
|
||||||
|
// do not wrap the message in parentheses
|
||||||
|
false
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,13 +318,23 @@ class RCCacheEntryFactory {
|
||||||
$userLink = ' <span class="' . $deletedClass . '">' .
|
$userLink = ' <span class="' . $deletedClass . '">' .
|
||||||
$this->context->msg( 'rev-deleted-user' )->escaped() . '</span>';
|
$this->context->msg( 'rev-deleted-user' )->escaped() . '</span>';
|
||||||
} else {
|
} else {
|
||||||
$userLink = Linker::userLink(
|
/**
|
||||||
$cacheEntry->mAttribs['rc_user'],
|
* UserLink requires parser to render which when run on thousands of records can add
|
||||||
$cacheEntry->mAttribs['rc_user_text'],
|
* up to significant amount of processing time.
|
||||||
ExternalUserNames::getLocal( $cacheEntry->mAttribs['rc_user_text'] ),
|
* @see RCCacheEntryFactory::newFromRecentChange
|
||||||
[
|
*/
|
||||||
'data-mw-revid' => $cacheEntry->mAttribs['rc_this_oldid']
|
$userLink = $this->userLinks->getWithSetCallback(
|
||||||
]
|
sprintf(
|
||||||
|
'%s:%s:%s',
|
||||||
|
$cacheEntry->mAttribs['rc_user_text'],
|
||||||
|
$this->context->getUser()->getName(),
|
||||||
|
$this->context->getLanguage()->getCode()
|
||||||
|
),
|
||||||
|
fn() => Linker::userLink(
|
||||||
|
$cacheEntry->mAttribs['rc_user'],
|
||||||
|
$cacheEntry->mAttribs['rc_user_text'],
|
||||||
|
ExternalUserNames::getLocal( $cacheEntry->mAttribs['rc_user_text'] )
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue