Patchwork [01,of,12] branches: avoid unnecessary changectx.branch() calls

login
register
mail settings
Submitter Brodie Rao
Date Nov. 16, 2013, 2:27 a.m.
Message ID <1e160d0fd711f4a709fe.1384568853@hit-nxdomain.opendns.com>
Download mbox | patch
Permalink /patch/2959/
State Superseded
Headers show

Comments

Brodie Rao - Nov. 16, 2013, 2:27 a.m.
# HG changeset patch
# User Brodie Rao <brodie@sf.io>
# Date 1384567912 18000
#      Fri Nov 15 21:11:52 2013 -0500
# Node ID 1e160d0fd711f4a709fe033a122c867d299a8afc
# Parent  c38c3fdc8b9317ba09e03ab09364c3800da7c50c
branches: avoid unnecessary changectx.branch() calls

This requires reading from the changelog, which can be costly over NFS.

Note that this does not totally remove reading from the changelog; we
still do that when calling changectx.closesbranch(). That call will be
removed in a later patch.

Running hg branches on the PyPy repo (with 996) over a busy NFS server,
before this change:

$ time hg --profile branches > /dev/null
   CallCount    Recursive     Total(s)    Inline(s) module:lineno(function)
        2042            0      2.2827      2.2827   <open>
        2036            0      0.9840      0.9840   <method 'close' of 'file' objects>
        2036            0      0.0464      0.0464   <method 'read' of 'file' objects>
        5233            0      0.1985      0.0453   mercurial.repoview:161(changelog)
       10462            0      0.0791      0.0314       mercurial.changelog:133(tip)
        5233            0      0.0388      0.0176       mercurial.localrepo:26(__get__)
       10462            0      0.0250      0.0126       <len>
        5233            0      0.0059      0.0039       mercurial.repoview:112(filterrevs)
       10462            0      0.0029      0.0029       <hash>
        2034            0      0.0444      0.0444   <method 'seek' of 'file' objects>
        5340            0      0.0390      0.0390   mercurial.revlog:296(rev)
        2582            0      0.0371      0.0371   <zlib.decompress>
        3155            0      0.1963      0.0366   mercurial.context:202(__init__)
        3155            0      0.1238      0.0306       mercurial.repoview:161(changelog)
        3155            0      0.0261      0.0080       mercurial.changelog:183(rev)
        9465            0      0.0061      0.0061       <isinstance>
        1096            0      0.0023      0.0023       <binascii.unhexlify>
        4251            0      0.0014      0.0014       <len>
        2059            0      3.7341      0.0332   mercurial.changelog:270(read)
        2059            0      3.6304      0.0307       mercurial.revlog:907(revision)
        2057            0      0.0262      0.0137       mercurial.changelog:28(decodeextra)
        4118            0      0.0094      0.0094       <method 'split' of 'str' objects>
        4118            0      0.0270      0.0048       mercurial.encoding:61(tolocal)
        2059            0      0.0040      0.0040       <method 'index' of 'str' objects>
       10462            0      0.0791      0.0314   mercurial.changelog:133(tip)
       10462            0      0.0289      0.0207       mercurial.changelog:190(node)
       10462            0      0.0188      0.0091       <len>
       52433        20932      0.0478      0.0310   <len>
       20932            0      0.0221      0.0168       mercurial.revlog:262(__len__)
        2059            0      3.6304      0.0307   mercurial.revlog:907(revision)

real    0m4.361s
user    0m0.986s
sys     0m0.237s

After this change:

$ time hg --profile branches > /dev/null
   CallCount    Recursive     Total(s)    Inline(s) module:lineno(function)
        1069            0      1.1098      1.1098   <open>
        1063            0      0.4865      0.4865   <method 'close' of 'file' objects>
        4122            0      0.1811      0.0404   mercurial.repoview:161(changelog)
        8240            0      0.0712      0.0272       mercurial.changelog:133(tip)
        4122            0      0.0378      0.0177       mercurial.localrepo:26(__get__)
        8240            0      0.0221      0.0115       <len>
        4122            0      0.0057      0.0033       mercurial.repoview:112(filterrevs)
        8240            0      0.0025      0.0025       <hash>
        3029            0      0.1979      0.0371   mercurial.context:202(__init__)
        3029            0      0.1278      0.0310       mercurial.repoview:161(changelog)
        3029            0      0.0230      0.0081       mercurial.changelog:183(rev)
        9087            0      0.0061      0.0061       <isinstance>
        1096            0      0.0026      0.0026       <binascii.unhexlify>
        4125            0      0.0014      0.0014       <len>
        4229            0      0.0337      0.0337   mercurial.revlog:296(rev)
        1061            0      0.0296      0.0296   <method 'seek' of 'file' objects>
        1063            0      0.0292      0.0292   <method 'read' of 'file' objects>
        8240            0      0.0712      0.0272   mercurial.changelog:133(tip)
        8240            0      0.0271      0.0196       mercurial.changelog:190(node)
        8240            0      0.0169      0.0083       <len>
       40476        16488      0.0422      0.0271   <len>
       16488            0      0.0193      0.0152       mercurial.revlog:262(__len__)
        1342            0      0.0241      0.0241   <zlib.decompress>
        9445            0      0.0336      0.0224   mercurial.changelog:190(node)
        9445            0      0.0112      0.0112       mercurial.revlog:317(node)
        1074            0      1.9102      0.0224   mercurial.changelog:270(read)
        1074            0      1.8397      0.0202       mercurial.revlog:907(revision)
        1073            0      0.0187      0.0099       mercurial.changelog:28(decodeextra)
        2148            0      0.0061      0.0061       <method 'split' of 'str' objects>
        2148            0      0.0184      0.0034       mercurial.encoding:61(tolocal)

real    0m2.402s
user    0m0.735s
sys     0m0.177s

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1008,7 +1008,7 @@  def branches(ui, repo, active=False, clo
 
     hexfunc = ui.debugflag and hex or short
 
-    activebranches = set([repo[n].branch() for n in repo.heads()])
+    allheads = set(repo.heads())
     branches = []
     for tag, heads in repo.branchmap().iteritems():
         for h in reversed(heads):
@@ -1019,12 +1019,12 @@  def branches(ui, repo, active=False, clo
                 break
         else:
             tip = repo[heads[-1]]
-        isactive = tag in activebranches and isopen
-        branches.append((tip, isactive, isopen))
-    branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
+        isactive = isopen and bool(set(heads) & allheads)
+        branches.append((tag, tip, isactive, isopen))
+    branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
                   reverse=True)
 
-    for ctx, isactive, isopen in branches:
+    for tag, ctx, isactive, isopen in branches:
         if (not active) or isactive:
             if isactive:
                 label = 'branches.active'
@@ -1037,16 +1037,16 @@  def branches(ui, repo, active=False, clo
             else:
                 label = 'branches.inactive'
                 notice = _(' (inactive)')
-            if ctx.branch() == repo.dirstate.branch():
+            if tag == repo.dirstate.branch():
                 label = 'branches.current'
-            rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
+            rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
             rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
                            'log.changeset changeset.%s' % ctx.phasestr())
-            tag = ui.label(ctx.branch(), label)
+            labeledtag = ui.label(tag, label)
             if ui.quiet:
-                ui.write("%s\n" % tag)
+                ui.write("%s\n" % labeledtag)
             else:
-                ui.write("%s %s%s\n" % (tag, rev, notice))
+                ui.write("%s %s%s\n" % (labeledtag, rev, notice))
 
 @command('bundle',
     [('f', 'force', None, _('run even when the destination is unrelated')),