Patchwork [1,of,2,V2] perf: add a perfnodemap command

login
register
mail settings
Submitter Boris Feld
Date Jan. 29, 2019, 3:47 p.m.
Message ID <3414a69b2e99e8fa605f.1548776823@localhost.localdomain>
Download mbox | patch
Permalink /patch/38155/
State Accepted
Headers show

Comments

Boris Feld - Jan. 29, 2019, 3:47 p.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1548460545 18000
#      Fri Jan 25 18:55:45 2019 -0500
# Node ID 3414a69b2e99e8fa605f63f9973894c80dd144b3
# Parent  7eb7637e34bf412374a165fbd234022a5a804683
# EXP-Topic perf-ext
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 3414a69b2e99
perf: add a perfnodemap command

The command focus on timing of the nodemap object itself.

Patch

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -1036,7 +1036,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)
@@ -1066,6 +1067,58 @@  def perfindex(ui, repo, **opts):
     timer(d, setup=setup)
     fm.end()
 
+@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