[PATCH 2 of 3] perf: add perflrucachedict command

Gregory Szorc gregory.szorc at gmail.com
Sun Dec 6 22:29:37 CST 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1449450470 28800
#      Sun Dec 06 17:07:50 2015 -0800
# Node ID 880e64102b0d530229379c8cc35c0ad13b94a635
# Parent  cc6da3323aebb1de5efaf7e923beac6fbee6420a
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 --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -1,14 +1,15 @@
 # perf.py - performance test routines
 '''helper extension to measure performance'''
 
 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
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
 
 def gettimer(ui, opts=None):
@@ -574,8 +575,84 @@ def perfbranchmap(ui, repo, full=False, 
 @command('perfloadmarkers')
 def perfloadmarkers(ui, repo):
     """benchmark the time to parse the on-disk markers for a repo
 
     Result is the number of markers in the repo."""
     timer, fm = gettimer(ui)
     timer(lambda: len(obsolete.obsstore(repo.svfs)))
     fm.end()
+
+ at 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]
+
+    # 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()
+


More information about the Mercurial-devel mailing list