1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-09-20 08:58:55 +02:00

Improve performance of mercurial arc diff

Summary:
arc diff on large mercurial repos was taking 14 seconds just to get
to the commit message prompt.  With these optimizations it takes 4.

- "ancestor(.) - ancestor(XYZ)" is expensive because it has to build the
entire 400000+ revision history for both.  "XYZ::. - XYZ" is much cheaper
because it only looks at the revisions between XYZ and the working directory.

- "hg outgoing" has to talk to the server, which is slow.  "hg log -r draft()"
gives us the same information and is much cheaper.  We fall back to 'outgoing'
on older versions of mercurial.

Of the remaining 4 seconds, 2.5 are spent in 'hg status', which is a bit harder
improve.

Test Plan: Ran arc diff on our hg repo. Verified it ran faster and the diff was created.

Reviewers: epriestley, sid0, bos, dschleimer

Reviewed By: epriestley

CC: aran, Korvin, tido

Differential Revision: https://secure.phabricator.com/D4838
This commit is contained in:
durham 2013-02-08 05:54:32 -08:00
parent 7f9c286338
commit db053e1eb7

View file

@ -106,9 +106,20 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
return $base;
}
list($err, $stdout) = $this->execManualLocal(
'outgoing --branch %s --style default',
// Mercurial 2.1 and up have phases which indicate if something is
// published or not. To find which revs are outgoing, it's much
// faster to check the phase instead of actually checking the server.
list($err) = $this->execManualLocal('help phase');
if (!$err) {
list($err, $stdout) = $this->execManualLocal(
'log --branch %s -r %s --style default',
$this->getBranchName(),
'draft()');
} else {
list($err, $stdout) = $this->execManualLocal(
'outgoing --branch %s --style default',
$this->getBranchName());
}
if (!$err) {
$logs = ArcanistMercurialParser::parseMercurialLog($stdout);
@ -175,13 +186,12 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
public function getLocalCommitInformation() {
if ($this->localCommitInfo === null) {
$base_commit = $this->getBaseCommit();
list($info) = $this->execxLocal(
"log --template '%C' --rev %s --branch %s --",
"{node}\1{rev}\1{author|emailuser}\1{author|email}\1".
"{date|rfc822date}\1{branch}\1{tag}\1{parents}\1{desc}\2",
hgsprintf(
'(ancestors(.) - ancestors(%s))',
$this->getBaseCommit()),
hgsprintf('(%s::. - %s)', $base_commit, $base_commit),
$this->getBranchName());
$logs = array_filter(explode("\2", $info));
@ -493,9 +503,10 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
}
public function getCommitMessageLog() {
$base_commit = $this->getBaseCommit();
list($stdout) = $this->execxLocal(
"log --template '{node}\\2{desc}\\1' --rev %s --branch %s --",
'ancestors(.) - ancestors('.$this->getBaseCommit().')',
hgsprintf('(%s::. - %s)', $base_commit, $base_commit),
$this->getBranchName());
$map = array();