Patchwork [2,of,2] obsolete: speed up unstable computation

login
register
mail settings
Submitter Laurent Charignon
Date May 4, 2015, 8:08 p.m.
Message ID <91b9f9b563ef51e2d4e0.1430770097@lcharignon-mbp.local>
Download mbox | patch
Permalink /patch/8875/
State Accepted
Headers show

Comments

Laurent Charignon - May 4, 2015, 8:08 p.m.
# HG changeset patch
# User Laurent Charignon <lcharignon@fb.com>
# Date 1430265083 25200
#      Tue Apr 28 16:51:23 2015 -0700
# Node ID 91b9f9b563ef51e2d4e0bda76d6bfa9e4d84efcf
# Parent  1fc6e61a669102a73d4ced63989704e4faf72993
obsolete: speed up unstable computation

Speed up the computation of the unstable revset by using the not public()
revset. In another series of patches, we optimize the not public() revset and
together it leads to a 50-100x speedup on the computation of unstable() for
our big repos.
Augie Fackler - May 5, 2015, 2:06 p.m.
On Mon, May 04, 2015 at 01:08:17PM -0700, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon@fb.com>
> # Date 1430265083 25200
> #      Tue Apr 28 16:51:23 2015 -0700
> # Node ID 91b9f9b563ef51e2d4e0bda76d6bfa9e4d84efcf
> # Parent  1fc6e61a669102a73d4ced63989704e4faf72993
> obsolete: speed up unstable computation

queued these, thanks

>
> Speed up the computation of the unstable revset by using the not public()
> revset. In another series of patches, we optimize the not public() revset and
> together it leads to a 50-100x speedup on the computation of unstable() for
> our big repos.
>
> diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
> --- a/mercurial/obsolete.py
> +++ b/mercurial/obsolete.py
> @@ -1110,13 +1110,17 @@
>  @cachefor('unstable')
>  def _computeunstableset(repo):
>      """the set of non obsolete revisions with obsolete parents"""
> -    # revset is not efficient enough here
> -    # we do (obsolete()::) - obsolete() by hand
> -    obs = getrevs(repo, 'obsolete')
> -    if not obs:
> -        return set()
> -    cl = repo.changelog
> -    return set(r for r in cl.descendants(obs) if r not in obs)
> +    revs = [(ctx.rev(), ctx) for ctx in
> +            repo.set('(not public()) and (not obsolete())')]
> +    revs.sort(key=lambda x:x[0])
> +    unstable = set()
> +    for rev, ctx in revs:
> +        # A rev is unstable if one of its parent is obsolete or unstable
> +        # this works since we traverse following growing rev order
> +        if util.any((x.obsolete() or (x.rev() in unstable))
> +                for x in ctx.parents()):
> +            unstable.add(rev)
> +    return unstable
>
>  @cachefor('suspended')
>  def _computesuspendedset(repo):
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -1110,13 +1110,17 @@ 
 @cachefor('unstable')
 def _computeunstableset(repo):
     """the set of non obsolete revisions with obsolete parents"""
-    # revset is not efficient enough here
-    # we do (obsolete()::) - obsolete() by hand
-    obs = getrevs(repo, 'obsolete')
-    if not obs:
-        return set()
-    cl = repo.changelog
-    return set(r for r in cl.descendants(obs) if r not in obs)
+    revs = [(ctx.rev(), ctx) for ctx in
+            repo.set('(not public()) and (not obsolete())')]
+    revs.sort(key=lambda x:x[0])
+    unstable = set()
+    for rev, ctx in revs:
+        # A rev is unstable if one of its parent is obsolete or unstable
+        # this works since we traverse following growing rev order
+        if util.any((x.obsolete() or (x.rev() in unstable))
+                for x in ctx.parents()):
+            unstable.add(rev)
+    return unstable
 
 @cachefor('suspended')
 def _computesuspendedset(repo):