[PATCH 3 of 4] revset-ancestors: use and iterator instead of a dequeu
Martin von Zweigbergk
martinvonz at google.com
Wed May 6 13:16:04 CDT 2015
On Mon, May 4, 2015 at 3:29 PM Pierre-Yves David <
pierre-yves.david at ens-lyon.org> wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david at fb.com>
> # Date 1395876090 25200
> # Wed Mar 26 16:21:30 2014 -0700
> # Node ID dffaf3d15f9587d3f4e00a03cd288108c5cc78fe
> # Parent 8aff772b686be3240fc04dc633dff18299ba7151
> revset-ancestors: use and iterator instead of a dequeu
>
> The dequeue was actually just used to be able to pop value one at a time.
> Building the dequeue mean we are reading all the input value at once at the
> beginning of the evaluation. This defeat the lazyness of revset.
>
> We replace the deque with iterator usage for the sake of simplicity and
> lazyness.
>
> This provide massive speedup to get the first result if the input set is
> big
>
> max(::all())
> before) wall 0.001917 comb 0.000000 user 0.000000 sys 0.000000 (best of
> 1115)
> after) wall 0.000107 comb 0.000000 user 0.000000 sys 0.000000 (best of
> 22222)
>
> diff --git a/mercurial/revset.py b/mercurial/revset.py
> --- a/mercurial/revset.py
> +++ b/mercurial/revset.py
> @@ -23,27 +23,30 @@ def _revancestors(repo, revs, followfirs
> else:
> cut = None
> cl = repo.changelog
>
> def iterate():
> - revqueue, inputrev = None, None
> h = []
>
> revs.sort(reverse=True)
> - revqueue = util.deque(revs)
> - if revqueue:
> - inputrev = revqueue.popleft()
> + irevs = iter(revs)
> + try:
> + inputrev = irevs.next()
> heapq.heappush(h, -inputrev)
> + except StopIteration:
> + irevs, inputrev = None, None
>
When revs is empty, h will also be empty. So before this patch we could
have done "if not revqueue: return" instead, which would have made it clear
that inputrev never needs to be initialized to None. Since "return" in a
generator can also be written "raise StopIteration", you could simply let
the above StopIteration through. Am I correct?
Since this was similar before and after your patch, perhaps such a
simplification should not be baked in to this patch. I do think it would be
cleaner to get it in before rather than after, though. But I may very well
be missing something here.
>
> seen = set()
> while h:
> current = -heapq.heappop(h)
> if current not in seen:
> - if inputrev and current == inputrev:
> - if revqueue:
> - inputrev = revqueue.popleft()
> + if irevs is not None and current == inputrev:
> + try:
> + inputrev = irevs.next()inputrev
> heapq.heappush(h, -inputrev)
> + except StopIteration:
> + irevs, inputrev = None, None
>
The straight-forwards translation would be "except StopIteration: pass",
wouldn't it?
> seen.add(current)
> yield current
> for parent in cl.parentrevs(current)[:cut]:
> if parent != node.nullrev:
> heapq.heappush(h, -parent)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20150506/ad90b9fc/attachment.html>
More information about the Mercurial-devel
mailing list