[PATCH 6 of 6 frozen-repos] commands.log: operate on frozen repository

Gregory Szorc gregory.szorc at gmail.com
Sat Nov 21 19:14:03 CST 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1448152280 28800
#      Sat Nov 21 16:31:20 2015 -0800
# Node ID f8ab893d8dac5246224f330fafdea35c0bcef313
# Parent  ad891b362564b30ec69bc844a3fd98e73b6e032e
commands.log: operate on frozen repository

`hg log` is a read-only command. As such, it can use a frozen
repository instance so it isn't constantly performing changelog
freshness checks.

On a local Firefox repository with ~312,000 changesets, this
simple change results in `hg log -T '{rev}\n' > /dev/null`
with an empty/default hgrc becoming faster:

before: 7.81s
after:  6.11s
delta: -1.70s (78.2% of original

A full `hg log` shows similar percentage improvement:

before: 31.14s
after:  24.95s
delta:  -6.19s (80.1% of original)

I'm actually surprised the full `hg log` output showed a similar
percentage speedup: I would have expected it to only decrease by
~1.70s. But counting function calls does reveal that the full
template output incurs an extra changectx instantiation for each
revision as well as additional changelog accesses (for parents
I believe).

For comparison purposes, git 2.6.3 for the same count of commits on
a Git conversion of the Firefox repo takes ~1.85s for
`git log --pretty=%H` and ~2.36s for `git log`. We're 3.3x slower
for printing revisions (4.2x before) and 10.6x slower for the
default template output (13.2x before).

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -4784,16 +4784,18 @@ def log(ui, repo, *pats, **opts):
     specifying revisions.
 
     See :hg:`help templates` for more about pre-packaged styles and
     specifying custom templates.
 
     Returns 0 on success.
 
     """
+    repo = repo.frozen()
+
     if opts.get('follow') and opts.get('rev'):
         opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
         del opts['follow']
 
     if opts.get('graph'):
         return cmdutil.graphlog(ui, repo, *pats, **opts)
 
     revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)


More information about the Mercurial-devel mailing list