chiark / gitweb /
Add some performance testing scripts
[stgit] / perf / perftest.py
1 import datetime, subprocess, sys
2
3 def duration(t1, t2):
4     d = t2 - t1
5     return 86400*d.days + d.seconds + 1e-6*d.microseconds
6
7 class Run(object):
8     def __init__(self):
9         self.__cwd = None
10         self.__log = []
11     def __call__(self, *cmd, **args):
12         kwargs = { 'cwd': self.__cwd }
13         if args.get('capture_stdout', False):
14             kwargs['stdout'] = subprocess.PIPE
15         start = datetime.datetime.now()
16         p = subprocess.Popen(cmd, **kwargs)
17         (out, err) = p.communicate()
18         stop = datetime.datetime.now()
19         self.__log.append((cmd, duration(start, stop)))
20         return out
21     def cd(self, dir):
22         self.__cwd = dir
23     def summary(self):
24         def pcmd(c): return ' '.join(c)
25         def ptime(t): return '%.3f' % t
26         (cs, times) = zip(*self.__log)
27         ttime = sum(times)
28         cl = max(len(pcmd(c)) for c in cs)
29         tl = max(len(ptime(t)) for t in list(times) + [ttime])
30         for (c, t) in self.__log:
31             print '%*s  %*s' % (tl, ptime(t), -cl, pcmd(c))
32         print '%*s' % (tl, ptime(ttime))
33
34 perftests = {}
35 perftestdesc = {}
36 def perftest(desc, name = None):
37     def decorator(f):
38         def g():
39             r = Run()
40             f(r)
41             r.summary()
42         perftests[name or f.__name__] = g
43         perftestdesc[name or f.__name__] = desc
44         return g
45     return decorator
46
47 def copy_testdir(dir):
48     tmp = dir + '.trash'
49     r = Run()
50     r('rsync', '-a', '--delete', dir + '.orig/', tmp)
51     return tmp
52
53 def new_rebase(r, ref):
54     top = r('stg', 'top', capture_stdout = True)
55     r('stg', 'pop', '-a')
56     r('git', 'reset', '--hard', ref)
57     r('stg', 'goto', top.strip())
58
59 def old_rebase(r, ref):
60     r('stg', 'rebase', ref)
61
62 def def_rebasetest(rebase, dir, tag):
63     @perftest('%s rebase onto %s in %s' % (rebase, tag, dir),
64               'rebase-%srebase-%s-%s' % (rebase, tag, dir))
65     def rebasetest(r):
66         r.cd(copy_testdir(dir))
67         r('stg', 'init')
68         if dir == 'synt':
69             r('stg', 'uncommit', '-n', '500')
70         else:
71             r('stg', 'uncommit', '-x', '-t', 'bomb-base')
72         if rebase == 'new':
73             new_rebase(r, tag)
74         else:
75             old_rebase(r, tag)
76 for rebase in ['old', 'new']:
77     for (dir, tag) in [('synt', 'add-file'),
78                        ('synt', 'modify-all'),
79                        ('linux', 'add-file')]:
80         def_rebasetest(rebase, dir, tag)
81
82 args = sys.argv[1:]
83 if len(args) == 0:
84     for (fun, desc) in sorted(perftestdesc.iteritems()):
85         print '%s: %s' % (fun, desc)
86 else:
87     for test in args:
88         perftests[test]()