Patchwork [4,of,4] revset: replace "repo.changelog" to avoid iteration for each "x in subset"

login
register
mail settings
Submitter Katsunori FUJIWARA
Date March 29, 2013, 4:16 p.m.
Message ID <78452fc8ab54526c7a31.1364573794@feefifofum>
Download mbox | patch
Permalink /patch/1218/
State Rejected
Headers show

Comments

Katsunori FUJIWARA - March 29, 2013, 4:16 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1364573132 -32400
# Node ID 78452fc8ab54526c7a31189327185a954e197397
# Parent  8af24dd8f88c5f8011ae32bb7256977c94eab238
revset: replace "repo.changelog" to avoid iteration for each "x in subset"

Before this patch, some revset predicates uses "repo.changelog" as
"subset" for sub-expressions to mean "whole revisions in repository".

But "changelog" doesn't have "__contains__()", and causes iteration
for each "x in subset" in sub-expressions.

This patch replaces "repo.changelog" by "_safesubset(repo)" to avoid
such iteration.

This patch affects predicates below:

  - rangeset(":")
  - ancestorspec("~")
  - parentspec("^")
  - matching
  - roots

Performance improvement can be measured by combination with predicates
examining "x in subset": "last", for example.

Results of "hg perfrevset" for each revspec (before/after this patch)
on the repository containing 40000 revisions are shown below:

  - "last(tip):last(tip)":
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 685)
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 13680)

  - "(last(tip))~1":
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 686)
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 1295)

  - "(last(tip))^1":
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 682)
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 1292)

  - "tip and matching(last(tip))":
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 1172)
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 6481)

  - "roots(last(tip))":
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 665)
    ! wall 0.000000 comb 0.000000 user 0.000000 sys 0.000000 (best of 1284)

Patch

diff -r 8af24dd8f88c -r 78452fc8ab54 mercurial/revset.py
--- a/mercurial/revset.py	Sat Mar 30 01:05:32 2013 +0900
+++ b/mercurial/revset.py	Sat Mar 30 01:05:32 2013 +0900
@@ -239,9 +239,9 @@ 
     return stringset(repo, subset, x)
 
 def rangeset(repo, subset, x, y):
-    cl = repo.changelog
-    m = getset(repo, cl, x)
-    n = getset(repo, cl, y)
+    rl = _safesubset(repo)
+    m = getset(repo, rl, x)
+    n = getset(repo, rl, y)
 
     if not m or not n:
         return []
@@ -350,7 +350,7 @@ 
         raise error.ParseError(_("~ expects a number"))
     ps = set()
     cl = repo.changelog
-    for r in getset(repo, cl, x):
+    for r in getset(repo, _safesubset(repo), x):
         for i in range(n):
             r = cl.parentrevs(r)[0]
         ps.add(r)
@@ -1163,7 +1163,7 @@ 
         raise error.ParseError(_("^ expects a number 0, 1, or 2"))
     ps = set()
     cl = repo.changelog
-    for r in getset(repo, cl, x):
+    for r in getset(repo, _safesubset(repo), x):
         if n == 0:
             ps.add(r)
         elif n == 1:
@@ -1281,7 +1281,7 @@ 
     # i18n: "matching" is a keyword
     l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
 
-    revs = getset(repo, repo.changelog, l[0])
+    revs = getset(repo, _safesubset(repo), l[0])
 
     fieldlist = ['metadata']
     if len(l) > 1:
@@ -1379,7 +1379,7 @@ 
     """``roots(set)``
     Changesets in set with no parent changeset in set.
     """
-    s = set(getset(repo, repo.changelog, x))
+    s = set(getset(repo, _safesubset(repo), x))
     subset = [r for r in subset if r in s]
     cs = _children(repo, subset, s)
     return [r for r in subset if r not in cs]