Patchwork revset: don't recreate matcher for every revision

login
register
mail settings
Submitter Martin von Zweigbergk
Date Oct. 31, 2014, 7:47 p.m.
Message ID <7d723652e38542853e52.1414784839@handduk2.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/6501/
State Accepted
Headers show

Comments

Martin von Zweigbergk - Oct. 31, 2014, 7:47 p.m.
# HG changeset patch
# User Martin von Zweigbergk <martinvonz@google.com>
# Date 1414777296 25200
#      Fri Oct 31 10:41:36 2014 -0700
# Branch stable
# Node ID 7d723652e38542853e529a6aa8264785257e9adf
# Parent  5f202d50a7e5a29b7e2bde045bacb1b9ff0bb04d
revset: don't recreate matcher for every revision

The matcher variable 'm' in checkstatus() is reset to None on each
call, so the caching of the matcher no longer happens as it was
intended. This seems to be a regression in ed7b674824a3 (revset: added
lazyset implementation to checkstatus, 2014-01-03).

Fix by moving the cached matcher into the enclosing function so it's
actually cached across calls. This speeds up

  hg log -r 'modifies(mercurial/context.py)' >/dev/null

from 7.5s to 4s.

Also see similar fix in f2aeff8a87b6 (revset: avoid recalculating
filesets, 2014-10-22).
Matt Mackall - Oct. 31, 2014, 7:57 p.m.
On Fri, 2014-10-31 at 12:47 -0700, Martin von Zweigbergk wrote:
> # HG changeset patch
> # User Martin von Zweigbergk <martinvonz@google.com>
> # Date 1414777296 25200
> #      Fri Oct 31 10:41:36 2014 -0700
> # Branch stable
> # Node ID 7d723652e38542853e529a6aa8264785257e9adf
> # Parent  5f202d50a7e5a29b7e2bde045bacb1b9ff0bb04d
> revset: don't recreate matcher for every revision

Queued for stable, thanks.

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -526,14 +526,15 @@ 
 def checkstatus(repo, subset, pat, field):
     hasset = matchmod.patkind(pat) == 'set'
 
+    mcache = [None]
     def matches(x):
-        m = None
+        c = repo[x]
+        if not mcache[0] or hasset:
+            mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
+        m = mcache[0]
         fname = None
-        c = repo[x]
-        if not m or hasset:
-            m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
-            if not m.anypats() and len(m.files()) == 1:
-                fname = m.files()[0]
+        if not m.anypats() and len(m.files()) == 1:
+            fname = m.files()[0]
         if fname is not None:
             if fname not in c.files():
                 return False