Put a readthrough cache in front of inline context construction
Summary: Ref T13513. Inline comment context information is somewhat expensive to construct and can be cached. Add a readthrough cache on top of it. Test Plan: Loaded a source code changeset with many inline comments, used Darkconsole to inspect query activity. Saw caches get populated. Updated cache key, saw caches regenerate. Browsed Diffusion, nothing looked broken. Maniphest Tasks: T13513 Differential Revision: https://secure.phabricator.com/D21279
This commit is contained in:
@@ -67,17 +67,26 @@ final class DifferentialDiffInlineCommentQuery
|
|||||||
return $id_map;
|
return $id_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function newInlineContextFromCacheData(array $map) {
|
||||||
|
return PhabricatorDiffInlineCommentContext::newFromCacheData($map);
|
||||||
|
}
|
||||||
|
|
||||||
protected function newInlineContextMap(array $inlines) {
|
protected function newInlineContextMap(array $inlines) {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$map = array();
|
$map = array();
|
||||||
|
|
||||||
foreach ($inlines as $key => $inline) {
|
$changeset_ids = mpull($inlines, 'getChangesetID');
|
||||||
$changeset = id(new DifferentialChangesetQuery())
|
|
||||||
|
$changesets = id(new DifferentialChangesetQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($inline->getChangesetID()))
|
->withIDs($changeset_ids)
|
||||||
->needHunks(true)
|
->needHunks(true)
|
||||||
->executeOne();
|
->execute();
|
||||||
|
$changesets = mpull($changesets, null, 'getID');
|
||||||
|
|
||||||
|
foreach ($inlines as $key => $inline) {
|
||||||
|
$changeset = idx($changesets, $inline->getChangesetID());
|
||||||
|
|
||||||
if (!$changeset) {
|
if (!$changeset) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,4 +70,8 @@ final class DiffusionDiffInlineCommentQuery
|
|||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function newInlineContextFromCacheData(array $map) {
|
||||||
|
return PhabricatorDiffInlineCommentContext::newFromCacheData($map);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,26 @@ final class PhabricatorDiffInlineCommentContext
|
|||||||
private $bodyLines;
|
private $bodyLines;
|
||||||
private $tailLines;
|
private $tailLines;
|
||||||
|
|
||||||
|
public static function newFromCacheData(array $map) {
|
||||||
|
$context = new self();
|
||||||
|
|
||||||
|
$context->setFilename(idx($map, 'filename'));
|
||||||
|
$context->setHeadLines(idx($map, 'headLines'));
|
||||||
|
$context->setBodyLines(idx($map, 'bodyLines'));
|
||||||
|
$context->setTailLines(idx($map, 'tailLines'));
|
||||||
|
|
||||||
|
return $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newCacheDataMap() {
|
||||||
|
return array(
|
||||||
|
'filename' => $this->getFilename(),
|
||||||
|
'headLines' => $this->getHeadLines(),
|
||||||
|
'bodyLines' => $this->getBodyLines(),
|
||||||
|
'tailLines' => $this->getTailLines(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function setFilename($filename) {
|
public function setFilename($filename) {
|
||||||
$this->filename = $filename;
|
$this->filename = $filename;
|
||||||
return $this;
|
return $this;
|
||||||
|
|||||||
@@ -82,6 +82,16 @@ abstract class PhabricatorInlineComment
|
|||||||
return $this->storageObject;
|
return $this->storageObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getInlineCommentCacheFragment() {
|
||||||
|
$phid = $this->getPHID();
|
||||||
|
|
||||||
|
if ($phid === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('inline(%s)', $phid);
|
||||||
|
}
|
||||||
|
|
||||||
abstract protected function newStorageObject();
|
abstract protected function newStorageObject();
|
||||||
abstract public function getControllerURI();
|
abstract public function getControllerURI();
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
abstract class PhabricatorDiffInlineCommentQuery
|
abstract class PhabricatorDiffInlineCommentQuery
|
||||||
extends PhabricatorApplicationTransactionCommentQuery {
|
extends PhabricatorApplicationTransactionCommentQuery {
|
||||||
|
|
||||||
|
const INLINE_CONTEXT_CACHE_VERSION = 1;
|
||||||
|
|
||||||
private $fixedStates;
|
private $fixedStates;
|
||||||
private $needReplyToComments;
|
private $needReplyToComments;
|
||||||
private $publishedComments;
|
private $publishedComments;
|
||||||
@@ -19,6 +21,7 @@ abstract class PhabricatorDiffInlineCommentQuery
|
|||||||
array $comments);
|
array $comments);
|
||||||
|
|
||||||
abstract protected function newInlineContextMap(array $inlines);
|
abstract protected function newInlineContextMap(array $inlines);
|
||||||
|
abstract protected function newInlineContextFromCacheData(array $map);
|
||||||
|
|
||||||
final public function withFixedStates(array $states) {
|
final public function withFixedStates(array $states) {
|
||||||
$this->fixedStates = $states;
|
$this->fixedStates = $states;
|
||||||
@@ -268,16 +271,83 @@ abstract class PhabricatorDiffInlineCommentQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($need_context) {
|
if ($need_context) {
|
||||||
$context_map = $this->newInlineContextMap($need_context);
|
$this->loadInlineCommentContext($need_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($need_context as $key => $inline) {
|
return $inlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadInlineCommentContext(array $inlines) {
|
||||||
|
$cache_keys = array();
|
||||||
|
foreach ($inlines as $key => $inline) {
|
||||||
|
$object = $inline->newInlineCommentObject();
|
||||||
|
$fragment = $object->getInlineCommentCacheFragment();
|
||||||
|
|
||||||
|
if ($fragment === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache_keys[$key] = sprintf(
|
||||||
|
'%s.context(v%d)',
|
||||||
|
$fragment,
|
||||||
|
self::INLINE_CONTEXT_CACHE_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache = PhabricatorCaches::getMutableStructureCache();
|
||||||
|
|
||||||
|
$cache_map = $cache->getKeys($cache_keys);
|
||||||
|
|
||||||
|
$context_map = array();
|
||||||
|
$need_construct = array();
|
||||||
|
|
||||||
|
foreach ($inlines as $key => $inline) {
|
||||||
|
$cache_key = idx($cache_keys, $key);
|
||||||
|
|
||||||
|
if ($cache_key !== null) {
|
||||||
|
if (array_key_exists($cache_key, $cache_map)) {
|
||||||
|
$cache_data = $cache_map[$cache_key];
|
||||||
|
$context_map[$key] = $this->newInlineContextFromCacheData(
|
||||||
|
$cache_data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$need_construct[$key] = $inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($need_construct) {
|
||||||
|
$construct_map = $this->newInlineContextMap($need_construct);
|
||||||
|
|
||||||
|
$write_map = array();
|
||||||
|
foreach ($construct_map as $key => $context) {
|
||||||
|
if ($context === null) {
|
||||||
|
$cache_data = $context;
|
||||||
|
} else {
|
||||||
|
$cache_data = $this->newCacheDataFromInlineContext($context);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache_key = idx($cache_keys, $key);
|
||||||
|
if ($cache_key !== null) {
|
||||||
|
$write_map[$cache_key] = $cache_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($write_map) {
|
||||||
|
$cache->setKeys($write_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
$context_map += $construct_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($inlines as $key => $inline) {
|
||||||
$inline->attachInlineContext(idx($context_map, $key));
|
$inline->attachInlineContext(idx($context_map, $key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
protected function newCacheDataFromInlineContext(
|
||||||
|
PhabricatorInlineCommentContext $context) {
|
||||||
return $inlines;
|
return $context->newCacheDataMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
final protected function simplifyContext(array $lines, $is_head) {
|
final protected function simplifyContext(array $lines, $is_head) {
|
||||||
|
|||||||
Reference in New Issue
Block a user