chiark / gitweb /
Preserve the given author date during import
[stgit] / perf / perftest.py
1 import datetime, os, os.path, 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 __logfile(self, cmd):
12         fn = os.path.join(os.getcwd(), '%04d.log' % len(self.__log))
13         f = open(fn, 'w')
14         f.write(' '.join(cmd) + '\n' + '-'*70 + '\n\n')
15         f.close()
16         return fn
17     def __call__(self, *cmd, **args):
18         env = dict(os.environ)
19         env['STGIT_SUBPROCESS_LOG'] = 'profile:' + self.__logfile(cmd)
20         kwargs = { 'cwd': self.__cwd, 'env': env }
21         if args.get('capture_stdout', False):
22             kwargs['stdout'] = subprocess.PIPE
23         start = datetime.datetime.now()
24         p = subprocess.Popen(cmd, **kwargs)
25         (out, err) = p.communicate()
26         stop = datetime.datetime.now()
27         self.__log.append((cmd, duration(start, stop)))
28         return out
29     def cd(self, dir):
30         self.__cwd = dir
31     def summary(self):
32         def pcmd(c): return ' '.join(c)
33         def ptime(t): return '%.3f' % t
34         (cs, times) = zip(*self.__log)
35         ttime = sum(times)
36         cl = max(len(pcmd(c)) for c in cs)
37         tl = max(len(ptime(t)) for t in list(times) + [ttime])
38         for (c, t) in self.__log:
39             print '%*s  %*s' % (tl, ptime(t), -cl, pcmd(c))
40         print '%*s' % (tl, ptime(ttime))
41
42 perftests = {}
43 perftestdesc = {}
44 def perftest(desc, name = None):
45     def decorator(f):
46         def g():
47             r = Run()
48             f(r)
49             r.summary()
50         perftests[name or f.__name__] = g
51         perftestdesc[name or f.__name__] = desc
52         return g
53     return decorator
54
55 def copy_testdir(dir):
56     tmp = dir + '.trash'
57     r = Run()
58     r('rsync', '-a', '--delete', dir + '.orig/', tmp)
59     return tmp
60
61 def new_rebase(r, ref):
62     top = r('stg', 'top', capture_stdout = True)
63     r('stg', 'pop', '-a')
64     r('git', 'reset', '--hard', ref)
65     r('stg', 'goto', top.strip())
66
67 def old_rebase(r, ref):
68     r('stg', 'rebase', ref)
69
70 def def_rebasetest(rebase, dir, tag):
71     @perftest('%s rebase onto %s in %s' % (rebase, tag, dir),
72               'rebase-%srebase-%s-%s' % (rebase, tag, dir))
73     def rebasetest(r):
74         r.cd(copy_testdir(dir))
75         r('stg', 'init')
76         if dir == 'synt':
77             r('stg', 'uncommit', '-n', '500')
78         else:
79             r('stg', 'uncommit', '-x', '-t', 'bomb-base')
80         if rebase == 'new':
81             new_rebase(r, tag)
82         else:
83             old_rebase(r, tag)
84 for rebase in ['old', 'new']:
85     for (dir, tag) in [('synt', 'add-file'),
86                        ('synt', 'modify-all'),
87                        ('linux', 'add-file')]:
88         def_rebasetest(rebase, dir, tag)
89
90 args = sys.argv[1:]
91 if len(args) == 0:
92     for (fun, desc) in sorted(perftestdesc.iteritems()):
93         print '%s: %s' % (fun, desc)
94 else:
95     for test in args:
96         perftests[test]()