# HG changeset patch # User Gregory Szorc # Date 1449450470 28800 # Node ID 528cf1a73ae54454c946d21c2a27090b61cf02f8 # Parent aef5b606d3ee3db5504d694df0a3e3aaa7b7e07b perf: add perflrucachedict command It measures time to construct, perform gets, sets, or mixed mode operations on a cache of configurable size with variable numbers of operations. diff -r aef5b606d3ee -r 528cf1a73ae5 contrib/perf.py --- a/contrib/perf.py Sun Dec 06 22:22:09 2015 -0800 +++ b/contrib/perf.py Sun Dec 06 17:07:50 2015 -0800 @@ -4,6 +4,7 @@ from mercurial import cmdutil, scmutil, util, commands, obsolete from mercurial import repoview, branchmap, merge, copies, error import time, os, sys +import random import functools formatteropts = commands.formatteropts @@ -582,3 +583,80 @@ timer, fm = gettimer(ui) timer(lambda: len(obsolete.obsstore(repo.svfs))) fm.end() + +@command('perflrucachedict', formatteropts + + [('', 'size', 4, 'size of cache'), + ('', 'gets', 10000, 'number of key lookups'), + ('', 'sets', 10000, 'number of key sets'), + ('', 'mixed', 10000, 'number of mixed mode operations'), + ('', 'mixedgetfreq', 50, 'frequency of get vs set ops in mixed mode')], + norepo=True) +def perflrucache(ui, size=4, gets=10000, sets=10000, mixed=10000, + mixedgetfreq=50, **opts): + def doinit(): + for i in xrange(10000): + util.lrucachedict(size) + + values = [] + for i in xrange(size): + values.append(random.randint(0, sys.maxint)) + + # Get mode fills the cache and tests raw lookup performance with no + # eviction. + getseq = [] + for i in xrange(gets): + getseq.append(random.choice(values)) + + def dogets(): + d = util.lrucachedict(size) + for v in values: + d[v] = v + for key in getseq: + value = d[key] + value # silence pyflakes warning + + # Set mode tests insertion speed with cache eviction. + setseq = [] + for i in xrange(sets): + setseq.append(random.randint(0, sys.maxint)) + + def dosets(): + d = util.lrucachedict(size) + for v in setseq: + d[v] = v + + # Mixed mode randomly performs gets and sets with eviction. + mixedops = [] + for i in xrange(mixed): + r = random.randint(0, 100) + if r < mixedgetfreq: + op = 0 + else: + op = 1 + + mixedops.append((op, random.randint(0, size * 2))) + + def domixed(): + d = util.lrucachedict(size) + + for op, v in mixedops: + if op == 0: + try: + d[v] + except KeyError: + pass + else: + d[v] = v + + benches = [ + (doinit, 'init'), + (dogets, 'gets'), + (dosets, 'sets'), + (domixed, 'mixed') + ] + + for fn, title in benches: + timer, fm = gettimer(ui, opts) + timer(fn, title=title) + fm.end() + diff -r aef5b606d3ee -r 528cf1a73ae5 tests/test-contrib-perf.t --- a/tests/test-contrib-perf.t Sun Dec 06 22:22:09 2015 -0800 +++ b/tests/test-contrib-perf.t Sun Dec 06 17:07:50 2015 -0800 @@ -75,6 +75,8 @@ benchmark the time to parse the on-disk markers for a repo perflog (no help text available) perflookup (no help text available) + perflrucachedict + (no help text available) perfmanifest (no help text available) perfmergecalculate (no help text available) @@ -139,6 +141,11 @@ $ hg perflog 2>&1 | filter_perf_output $ hg perflookup 2 2>&1 | filter_perf_output ! result: 20 + $ hg perflrucache 2>&1 | filter_perf_output + ! init + ! gets + ! sets + ! mixed $ hg perfmanifest 2 2>&1 | filter_perf_output $ hg perfmergecalculate -r 3 2>&1 | filter_perf_output $ hg perfmoonwalk 2>&1 | filter_perf_output