1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-20 20:40:56 +01:00

Use RepositoryGraphCache to service diffusion.lastmodifiedquery

Summary:
Ref T2683. At least locally, browse views are now nearly instantaneous, even in Mercurial. We also fall back to what we were doing before if we miss or take too long, so this shouldn't make things very much worse even in extreme cases.

For a local `hg` repo, the time we spend pulling browse stuff has dropped from ~3,000ms to ~20ms. This is probably atypical, but not completely crazy or rigged or anything.

Test Plan: Viewed Git, Subversion and Mercurial repositories and observed dramatically better performance in Git and Mercurial as they took advantage of the cache.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley, jhurwitz

Maniphest Tasks: T2683

Differential Revision: https://secure.phabricator.com/D9047
This commit is contained in:
epriestley 2014-05-10 17:26:03 -07:00
parent e34ee684e1
commit e13369d208
3 changed files with 81 additions and 12 deletions

View file

@ -21,23 +21,28 @@ final class ConduitAPI_diffusion_lastmodifiedquery_Method
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$result = array(); $paths = $request->getValue('paths');
foreach ($request->getValue('paths') as $path => $commit) { $results = $this->loadCommitsFromCache($paths);
foreach ($paths as $path => $commit) {
if (array_key_exists($path, $results)) {
continue;
}
list($hash) = $repository->execxLocalCommand( list($hash) = $repository->execxLocalCommand(
'log -n1 --format=%%H %s -- %s', 'log -n1 --format=%%H %s -- %s',
$commit, $commit,
$path); $path);
$result[$path] = trim($hash); $results[$path] = trim($hash);
} }
return $result; return $results;
} }
protected function getSVNResult(ConduitAPIRequest $request) { protected function getSVNResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$result = array(); $results = array();
foreach ($request->getValue('paths') as $path => $commit) { foreach ($request->getValue('paths') as $path => $commit) {
$history_result = DiffusionQuery::callConduitWithDiffusionRequest( $history_result = DiffusionQuery::callConduitWithDiffusionRequest(
$request->getUser(), $request->getUser(),
@ -55,30 +60,93 @@ final class ConduitAPI_diffusion_lastmodifiedquery_Method
$history_array = DiffusionPathChange::newFromConduit( $history_array = DiffusionPathChange::newFromConduit(
$history_result['pathChanges']); $history_result['pathChanges']);
if ($history_array) { if ($history_array) {
$result[$path] = head($history_array) $results[$path] = head($history_array)
->getCommit() ->getCommit()
->getCommitIdentifier(); ->getCommitIdentifier();
} }
} }
return $result; return $results;
} }
protected function getMercurialResult(ConduitAPIRequest $request) { protected function getMercurialResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$result = array(); $paths = $request->getValue('paths');
foreach ($request->getValue('paths') as $path => $commit) { $results = $this->loadCommitsFromCache($paths);
foreach ($paths as $path => $commit) {
if (array_key_exists($path, $results)) {
continue;
}
list($hash) = $repository->execxLocalCommand( list($hash) = $repository->execxLocalCommand(
'log --template %s --limit 1 --removed --rev %s -- %s', 'log --template %s --limit 1 --removed --rev %s -- %s',
'{node}', '{node}',
hgsprintf('reverse(ancestors(%s))', $commit), hgsprintf('reverse(ancestors(%s))', $commit),
nonempty(ltrim($path, '/'), '.')); nonempty(ltrim($path, '/'), '.'));
$result[$path] = trim($hash); $results[$path] = trim($hash);
} }
return $result; return $results;
}
private function loadCommitsFromCache(array $map) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$path_map = id(new DiffusionPathIDQuery(array_keys($map)))
->loadPathIDs();
$commit_query = id(new DiffusionCommitQuery())
->setViewer($drequest->getUser())
->withRepository($repository)
->withIdentifiers(array_values($map));
$commit_query->execute();
$commit_map = $commit_query->getIdentifierMap();
$commit_map = mpull($commit_map, 'getID');
$graph_cache = new PhabricatorRepositoryGraphCache();
$results = array();
foreach ($map as $path => $commit) {
$path_id = idx($path_map, $path);
if (!$path_id) {
continue;
}
$commit_id = idx($commit_map, $commit);
if (!$commit_id) {
continue;
}
$cache_result = $graph_cache->loadLastModifiedCommitID(
$commit_id,
$path_id);
if ($cache_result !== false) {
$results[$path] = $cache_result;
}
}
if ($results) {
$commits = id(new DiffusionCommitQuery())
->setViewer($drequest->getUser())
->withRepository($repository)
->withIDs($results)
->execute();
foreach ($results as $path => $id) {
$commit = idx($commits, $id);
if ($commit) {
$results[$path] = $commit->getCommitIdentifier();
} else {
unset($results[$path]);
}
}
}
return $results;
} }
} }

View file

@ -113,6 +113,7 @@ final class DiffusionBrowseTableView extends DiffusionView {
'uri' => (string)$request->generateURI( 'uri' => (string)$request->generateURI(
array( array(
'action' => 'lastmodified', 'action' => 'lastmodified',
'stable' => true,
)), )),
'map' => $need_pull, 'map' => $need_pull,
)); ));

View file

@ -200,7 +200,7 @@ final class PhabricatorRepositoryGraphCache {
if ($prefix === null) { if ($prefix === null) {
$self = get_class($this); $self = get_class($this);
$size = $this->getBucketSize(); $size = $this->getBucketSize();
$prefix = "{$self}:{$size}:1:"; $prefix = "{$self}:{$size}:2:";
} }
return $prefix.$bucket_key; return $prefix.$bucket_key;