[PATCH 7 of 7] perf: add a perfnodemap command

Boris Feld boris.feld at octobus.net
Mon Jan 28 15:10:59 EST 2019


# HG changeset patch
# User Boris Feld <boris.feld at octobus.net>
# Date 1548460545 18000
#      Fri Jan 25 18:55:45 2019 -0500
# Node ID 884df78c77a1c3b11ca2e5728ae6b5ebd7f6d2aa
# Parent  1e135ddcbdd182a6b7ae7b121d254fb58c7fd658
# EXP-Topic perf-ext
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 884df78c77a1
perf: add a perfnodemap command

The command focus on timing of the nodemap object itself.

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -1038,7 +1038,8 @@ def perfindex(ui, repo, **opts):
     * -10000:
     * -10000: + 0
 
-    It is not currently possible to check for lookup of a missing node."""
+    It is not currently possible to check for lookup of a missing node. For
+    deeper lookup benchmarking, checkout the `perfnodemap` command."""
     import mercurial.revlog
     opts = _byteskwargs(opts)
     timer, fm = gettimer(ui, opts)
@@ -1068,6 +1069,58 @@ def perfindex(ui, repo, **opts):
     timer(d, setup=setup)
     fm.end()
 
+ at command(b'perfnodemap', [
+            (b'', b'rev', [], b'revision to be looked up (default tip)'),
+    ] + formatteropts)
+def perfnodemap(ui, repo, **opts):
+    """benchmark the time necessary to look up revision from a cold nodemap
+
+    Depending on the implementation, the amount and order of revision we look
+    up can varies. Example of useful set to test:
+    * tip
+    * 0
+    * -10:
+    * :10
+    * -10: + :10
+    * :10: + -10:
+    * -10000:
+    * -10000: + 0
+
+    The command currently focus on valid binary lookup. Benchmarking for
+    hexlookup, prefix lookup and missing lookup would also be valuable.
+    """
+    import mercurial.revlog
+    opts = _byteskwargs(opts)
+    timer, fm = gettimer(ui, opts)
+    mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
+
+    unfi = repo.unfiltered()
+    # find the filecache func directly
+    # This avoid polluting the benchmark with the filecache logic
+    makecl = unfi.__class__.changelog.func
+    if not opts[b'rev']:
+        raise error.Abort('use --rev to specify revisions to look up')
+    revs = scmutil.revrange(repo, opts[b'rev'])
+    cl = repo.changelog
+    nodes = [cl.node(r) for r in revs]
+
+    # use a list to pass reference to a nodemap from one closure to the next
+    nodeget = [None]
+    def setnodeget():
+        # probably not necessary, but for good measure
+        clearchangelog(unfi)
+        nodeget[0] = makecl(unfi).nodemap.get
+
+    def setup():
+        setnodeget()
+    def d():
+        get = nodeget[0]
+        for n in nodes:
+            get(n)
+
+    timer(d, setup=setup)
+    fm.end()
+
 @command(b'perfstartup', formatteropts)
 def perfstartup(ui, repo, **opts):
     opts = _byteskwargs(opts)
diff --git a/tests/test-contrib-perf.t b/tests/test-contrib-perf.t
--- a/tests/test-contrib-perf.t
+++ b/tests/test-contrib-perf.t
@@ -109,6 +109,8 @@ perfstatus
    perfmoonwalk  benchmark walking the changelog backwards
    perfnodelookup
                  (no help text available)
+   perfnodemap   benchmark the time necessary to look up revision from a cold
+                 nodemap
    perfparents   (no help text available)
    perfpathcopies
                  benchmark the copy tracing logic


More information about the Mercurial-devel mailing list