# HG changeset patch # User Boris Feld # Date 1548460545 18000 # Node ID c9ff9388955094e89d3a3870bba8bb0001d55c45 # Parent 9cb51e74e9ad858f2d988579eaf4a0c8f80ce1c0 perf: add a perfnodemap command The command focus on timing of the nodemap object itself. diff -r 9cb51e74e9ad -r c9ff93889550 contrib/perf.py --- a/contrib/perf.py Wed Jan 30 13:07:20 2019 -0800 +++ b/contrib/perf.py Fri Jan 25 18:55:45 2019 -0500 @@ -1036,7 +1036,8 @@ * -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 @@ 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 -r 9cb51e74e9ad -r c9ff93889550 tests/test-contrib-perf.t --- a/tests/test-contrib-perf.t Wed Jan 30 13:07:20 2019 -0800 +++ b/tests/test-contrib-perf.t Fri Jan 25 18:55:45 2019 -0500 @@ -109,6 +109,8 @@ 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