@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+81 -12
+79 -11
src/applications/diffusion/conduit/ConduitAPI_diffusion_lastmodifiedquery_Method.php
··· 21 21 $drequest = $this->getDiffusionRequest(); 22 22 $repository = $drequest->getRepository(); 23 23 24 - $result = array(); 25 - foreach ($request->getValue('paths') as $path => $commit) { 24 + $paths = $request->getValue('paths'); 25 + $results = $this->loadCommitsFromCache($paths); 26 + 27 + foreach ($paths as $path => $commit) { 28 + if (array_key_exists($path, $results)) { 29 + continue; 30 + } 26 31 list($hash) = $repository->execxLocalCommand( 27 32 'log -n1 --format=%%H %s -- %s', 28 33 $commit, 29 34 $path); 30 - $result[$path] = trim($hash); 35 + $results[$path] = trim($hash); 31 36 } 32 37 33 - return $result; 38 + return $results; 34 39 } 35 40 36 41 protected function getSVNResult(ConduitAPIRequest $request) { 37 42 $drequest = $this->getDiffusionRequest(); 38 43 $repository = $drequest->getRepository(); 39 44 40 - $result = array(); 45 + $results = array(); 41 46 foreach ($request->getValue('paths') as $path => $commit) { 42 47 $history_result = DiffusionQuery::callConduitWithDiffusionRequest( 43 48 $request->getUser(), ··· 55 60 $history_array = DiffusionPathChange::newFromConduit( 56 61 $history_result['pathChanges']); 57 62 if ($history_array) { 58 - $result[$path] = head($history_array) 63 + $results[$path] = head($history_array) 59 64 ->getCommit() 60 65 ->getCommitIdentifier(); 61 66 } 62 67 } 63 68 64 - return $result; 69 + return $results; 65 70 } 66 71 67 72 protected function getMercurialResult(ConduitAPIRequest $request) { 68 73 $drequest = $this->getDiffusionRequest(); 69 74 $repository = $drequest->getRepository(); 70 75 71 - $result = array(); 72 - foreach ($request->getValue('paths') as $path => $commit) { 76 + $paths = $request->getValue('paths'); 77 + $results = $this->loadCommitsFromCache($paths); 78 + 79 + foreach ($paths as $path => $commit) { 80 + if (array_key_exists($path, $results)) { 81 + continue; 82 + } 83 + 73 84 list($hash) = $repository->execxLocalCommand( 74 85 'log --template %s --limit 1 --removed --rev %s -- %s', 75 86 '{node}', 76 87 hgsprintf('reverse(ancestors(%s))', $commit), 77 88 nonempty(ltrim($path, '/'), '.')); 78 - $result[$path] = trim($hash); 89 + $results[$path] = trim($hash); 79 90 } 80 91 81 - return $result; 92 + return $results; 93 + } 94 + 95 + private function loadCommitsFromCache(array $map) { 96 + $drequest = $this->getDiffusionRequest(); 97 + $repository = $drequest->getRepository(); 98 + 99 + $path_map = id(new DiffusionPathIDQuery(array_keys($map))) 100 + ->loadPathIDs(); 101 + 102 + $commit_query = id(new DiffusionCommitQuery()) 103 + ->setViewer($drequest->getUser()) 104 + ->withRepository($repository) 105 + ->withIdentifiers(array_values($map)); 106 + $commit_query->execute(); 107 + 108 + $commit_map = $commit_query->getIdentifierMap(); 109 + $commit_map = mpull($commit_map, 'getID'); 110 + 111 + $graph_cache = new PhabricatorRepositoryGraphCache(); 112 + 113 + $results = array(); 114 + foreach ($map as $path => $commit) { 115 + $path_id = idx($path_map, $path); 116 + if (!$path_id) { 117 + continue; 118 + } 119 + $commit_id = idx($commit_map, $commit); 120 + if (!$commit_id) { 121 + continue; 122 + } 123 + 124 + $cache_result = $graph_cache->loadLastModifiedCommitID( 125 + $commit_id, 126 + $path_id); 127 + 128 + if ($cache_result !== false) { 129 + $results[$path] = $cache_result; 130 + } 131 + } 132 + 133 + if ($results) { 134 + $commits = id(new DiffusionCommitQuery()) 135 + ->setViewer($drequest->getUser()) 136 + ->withRepository($repository) 137 + ->withIDs($results) 138 + ->execute(); 139 + foreach ($results as $path => $id) { 140 + $commit = idx($commits, $id); 141 + if ($commit) { 142 + $results[$path] = $commit->getCommitIdentifier(); 143 + } else { 144 + unset($results[$path]); 145 + } 146 + } 147 + } 148 + 149 + return $results; 82 150 } 83 151 84 152 }
+1
src/applications/diffusion/view/DiffusionBrowseTableView.php
··· 113 113 'uri' => (string)$request->generateURI( 114 114 array( 115 115 'action' => 'lastmodified', 116 + 'stable' => true, 116 117 )), 117 118 'map' => $need_pull, 118 119 ));
+1 -1
src/applications/repository/graphcache/PhabricatorRepositoryGraphCache.php
··· 200 200 if ($prefix === null) { 201 201 $self = get_class($this); 202 202 $size = $this->getBucketSize(); 203 - $prefix = "{$self}:{$size}:1:"; 203 + $prefix = "{$self}:{$size}:2:"; 204 204 } 205 205 206 206 return $prefix.$bucket_key;