rev |
line source |
bos@222
|
1 #!/usr/bin/python
|
bos@222
|
2 #
|
bos@222
|
3 # Silly benchmarking program, to give a vague idea of how fast a few
|
bos@222
|
4 # tools are on a handful of common operations.
|
bos@222
|
5 #
|
bos@222
|
6 # Use a fairly big and real source tarball to test with: Firefox
|
bos@222
|
7 # 2.0.0.3 (37622 files, 5374 directories, 343MB unpacked onto
|
bos@222
|
8 # 4KB-blocksize ext3).
|
bos@222
|
9
|
bos@222
|
10 import csv
|
bos@222
|
11 import os
|
bos@222
|
12 import shutil
|
bos@222
|
13 import sys
|
bos@222
|
14 import tempfile
|
bos@222
|
15 import time
|
bos@222
|
16 import urllib2
|
bos@222
|
17
|
bos@222
|
18 url = 'ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.3/source/firefox-2.0.0.3-source.tar.bz2'
|
bos@222
|
19
|
bos@222
|
20 class CommandFailure(Exception):
|
bos@222
|
21 pass
|
bos@222
|
22
|
bos@222
|
23 class rcs(object):
|
bos@222
|
24 def __init__(self):
|
bos@222
|
25 self.logfp = open(self.__class__.__name__ + '.csv', 'w')
|
bos@222
|
26 self.csv = csv.writer(self.logfp)
|
bos@222
|
27
|
bos@222
|
28 def download(self):
|
bos@222
|
29 name = url[url.rfind('/')+1:]
|
bos@222
|
30 path = os.path.join(os.environ['HOME'], name)
|
bos@222
|
31 if not os.path.isfile(path):
|
bos@222
|
32 ofp = open(path + '.part', 'wb')
|
bos@222
|
33 try:
|
bos@222
|
34 ifp = urllib2.urlopen(url)
|
bos@222
|
35 nbytes = ifp.info()['content-length']
|
bos@222
|
36 sys.stdout.write('%s: %s bytes ' % (name, nbytes))
|
bos@222
|
37 sys.stdout.flush()
|
bos@222
|
38 while True:
|
bos@222
|
39 data = ifp.read(131072)
|
bos@222
|
40 if not data: break
|
bos@222
|
41 sys.stdout.write('.')
|
bos@222
|
42 sys.stdout.flush()
|
bos@222
|
43 ofp.write(data)
|
bos@222
|
44 del ofp
|
bos@222
|
45 os.rename(path + '.part', path)
|
bos@222
|
46 except:
|
bos@222
|
47 if os.path.exists(path + '.part'):
|
bos@222
|
48 os.unlink(path + '.part')
|
bos@222
|
49 if os.path.exists(path):
|
bos@222
|
50 os.unlink(path)
|
bos@222
|
51 raise
|
bos@222
|
52 return path
|
bos@222
|
53
|
bos@222
|
54 def run(self, args, mustsucceed=True):
|
bos@222
|
55 ret = os.spawnvp(os.P_WAIT, args[0], args)
|
bos@222
|
56 if ret < 0:
|
bos@222
|
57 msg = 'killed by signal %d' % (-ret)
|
bos@222
|
58 if ret > 0:
|
bos@222
|
59 msg = 'exited with status %d' % (ret)
|
bos@222
|
60 if ret:
|
bos@222
|
61 if mustsucceed:
|
bos@222
|
62 raise CommandFailure('%s: %s' % (msg, ' '.join(args)))
|
bos@222
|
63 print >> sys.stderr, 'WARNING: %s: %s' % (msg, ' '.join(args))
|
bos@222
|
64
|
bos@222
|
65 def time(self, *args, **kwargs):
|
bos@222
|
66 start = time.time()
|
bos@222
|
67 self.run(*args, **kwargs)
|
bos@222
|
68 end = time.time()
|
bos@222
|
69 return end - start
|
bos@222
|
70
|
bos@222
|
71 def logtime(self, name, elapsed, rest=[]):
|
bos@222
|
72 self.log('time:' + name, '%.3f' % elapsed, rest)
|
bos@222
|
73
|
bos@222
|
74 def log(self, name, value, rest=[]):
|
bos@222
|
75 item = (name, value, repr(rest))
|
bos@222
|
76 print ' '.join(item)
|
bos@222
|
77 self.csv.writerow(item)
|
bos@222
|
78 self.logfp.flush()
|
bos@222
|
79
|
bos@222
|
80 def unpack(self):
|
bos@222
|
81 tarball = self.download()
|
bos@222
|
82 t = self.time(['tar', '-C', self.wdir, '-jxf', tarball])
|
bos@222
|
83 self.logtime('internal:untar', t)
|
bos@222
|
84 for name in os.listdir(os.path.join(self.wdir, 'mozilla')):
|
bos@222
|
85 os.rename(os.path.join(self.wdir, 'mozilla', name),
|
bos@222
|
86 os.path.join(self.wdir, name))
|
bos@222
|
87
|
bos@222
|
88 def cleanup(self):
|
bos@222
|
89 pass
|
bos@222
|
90
|
bos@222
|
91 def add(self, paths):
|
bos@222
|
92 pass
|
bos@222
|
93
|
bos@222
|
94 def commit(self, msg, paths):
|
bos@222
|
95 pass
|
bos@222
|
96
|
bos@222
|
97 def status(self, path):
|
bos@222
|
98 pass
|
bos@222
|
99
|
bos@222
|
100 def remove(self, path):
|
bos@222
|
101 pass
|
bos@222
|
102
|
bos@222
|
103
|
bos@222
|
104 class subversion(rcs):
|
bos@222
|
105 def __init__(self, root):
|
bos@222
|
106 rcs.__init__(self)
|
bos@222
|
107 self.repo = os.path.join(root, 'repo')
|
bos@222
|
108 self.wdir = os.path.join(root, 'wc')
|
bos@222
|
109 create = self.time(['svnadmin', 'create', '--fs-type=fsfs', self.repo])
|
bos@222
|
110 self.logtime('svn:create', create)
|
bos@222
|
111 co = self.time(['svn', 'co', 'file://' + self.repo, self.wdir])
|
bos@222
|
112 self.logtime('svn:co', co)
|
bos@222
|
113 self.logtime('init', create + co)
|
bos@222
|
114 os.chdir(self.wdir)
|
bos@222
|
115
|
bos@222
|
116 def dropmeta(self, names):
|
bos@222
|
117 return [n for n in names if os.path.basename(n) != '.svn']
|
bos@222
|
118
|
bos@222
|
119 def add(self, paths):
|
bos@222
|
120 t = self.time(['svn', 'add', '-q'] + paths)
|
bos@222
|
121 self.logtime('add %r' % paths, t)
|
bos@222
|
122
|
bos@222
|
123 def commit(self, msg, paths=[]):
|
bos@222
|
124 if paths:
|
bos@222
|
125 t = self.time(['svn', 'ci', '-q', '-m', msg] + paths)
|
bos@222
|
126 else:
|
bos@222
|
127 t = self.time(['svn', 'ci', '-q', '-m', msg])
|
bos@222
|
128 self.logtime('commit %r' % paths, t)
|
bos@222
|
129
|
bos@222
|
130
|
bos@222
|
131 class mercurial(rcs):
|
bos@222
|
132 def __init__(self, root):
|
bos@222
|
133 rcs.__init__(self)
|
bos@222
|
134 self.repo = os.path.join(root, 'repo')
|
bos@222
|
135 self.wdir = self.repo
|
bos@222
|
136 init = self.time(['hg', 'init', self.repo])
|
bos@222
|
137 self.logtime('init', init)
|
bos@222
|
138 os.chdir(self.wdir)
|
bos@222
|
139
|
bos@222
|
140 def dropmeta(self, names):
|
bos@222
|
141 return [n for n in names if os.path.basename(n) != '.hg']
|
bos@222
|
142
|
bos@222
|
143 def add(self, paths):
|
bos@222
|
144 t = self.time(['hg', 'add', '-q'] + paths)
|
bos@222
|
145 self.logtime('add %r' % paths, t)
|
bos@222
|
146
|
bos@222
|
147 def commit(self, msg, paths=[]):
|
bos@222
|
148 if paths:
|
bos@222
|
149 t = self.time(['hg', 'ci', '-q', '-m', msg] + paths)
|
bos@222
|
150 else:
|
bos@222
|
151 t = self.time(['hg', 'ci', '-q', '-m', msg])
|
bos@222
|
152 self.logtime('commit %r' % paths, t)
|
bos@222
|
153
|
bos@222
|
154 def benchmark(cls):
|
bos@222
|
155 oldcwd = os.getcwd()
|
bos@222
|
156 root = tempfile.mkdtemp(prefix='sillybench.')
|
bos@222
|
157 try:
|
bos@222
|
158 print 'root', root
|
bos@222
|
159 inst = cls(root)
|
bos@222
|
160 inst.unpack()
|
bos@222
|
161 names = inst.dropmeta(os.listdir('.'))
|
bos@222
|
162 dirs = [n for n in names if os.path.isdir(n)]
|
bos@222
|
163 nondirs = [n for n in names if not os.path.isdir(n)]
|
bos@222
|
164 dirs.sort(key=hash)
|
bos@222
|
165 names.sort(key=hash)
|
bos@222
|
166 for d in dirs[:len(dirs)/2]:
|
bos@222
|
167 inst.add([d])
|
bos@222
|
168 inst.commit('Add %r' % d, [d])
|
bos@222
|
169 inst.add(dirs[len(dirs)/2:] + names)
|
bos@222
|
170 inst.commit('Add remaining dirs and files')
|
bos@222
|
171 finally:
|
bos@222
|
172 print >> sys.stderr, '[cleaning up...]'
|
bos@222
|
173 shutil.rmtree(root)
|
bos@222
|
174 os.chdir(oldcwd)
|
bos@222
|
175
|
bos@222
|
176 benchmark(mercurial)
|
bos@222
|
177 #benchmark(subversion)
|