contrib/perf.py
changeset 27286 528cf1a73ae5
parent 27100 8d5dba93aa4f
child 27303 57bd9c5431a5
--- 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()
+