revset: speedup matching() by stopping the match early if a field does not match
Rather than getting all the fields that are being matches from every revision
and then comparing them to those of the target revision, compare each field one
by one and stop the match as soon as there is a match failure.
This can greatly reduce the match time when matching multiple fields.
The impact on match time when matching a single field seems negligible
(according to my measurements).
--- a/mercurial/revset.py Fri Apr 13 13:35:45 2012 +0200
+++ b/mercurial/revset.py Fri Apr 13 13:46:49 2012 +0200
@@ -970,19 +970,22 @@
raise error.ParseError(
_("unexpected field name passed to matching: %s") % info)
getfieldfuncs.append(getfield)
-
# convert the getfield array of functions into a "getinfo" function
# which returns an array of field values (or a single value if there
# is only one field to match)
- if len(getfieldfuncs) == 1:
- getinfo = getfieldfuncs[0]
- else:
- getinfo = lambda r: [f(r) for f in getfieldfuncs]
+ getinfo = lambda r: [f(r) for f in getfieldfuncs]
matches = []
for rev in revs:
target = getinfo(rev)
- matches += [r for r in subset if getinfo(r) == target]
+ for r in subset:
+ match = True
+ for n, f in enumerate(getfieldfuncs):
+ if target[n] != f(r):
+ match = False
+ break
+ if match:
+ matches.append(r)
if len(revs) > 1:
matches = sorted(set(matches))
return matches