hgbook
diff contrib/sillybench.py @ 812:42e2c9d47ef4
Minor changes and translation of code snippets for Ch.12.
author | Giulio@puck |
---|---|
date | Sat Aug 15 15:15:39 2009 +0200 (2009-08-15) |
parents | b2b593eb56e7 |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/contrib/sillybench.py Sat Aug 15 15:15:39 2009 +0200 1.3 @@ -0,0 +1,177 @@ 1.4 +#!/usr/bin/python 1.5 +# 1.6 +# Silly benchmarking program, to give a vague idea of how fast a few 1.7 +# tools are on a handful of common operations. 1.8 +# 1.9 +# Use a fairly big and real source tarball to test with: Firefox 1.10 +# 2.0.0.3 (37622 files, 5374 directories, 343MB unpacked onto 1.11 +# 4KB-blocksize ext3). 1.12 + 1.13 +import csv 1.14 +import os 1.15 +import shutil 1.16 +import sys 1.17 +import tempfile 1.18 +import time 1.19 +import urllib2 1.20 + 1.21 +url = 'ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.3/source/firefox-2.0.0.3-source.tar.bz2' 1.22 + 1.23 +class CommandFailure(Exception): 1.24 + pass 1.25 + 1.26 +class rcs(object): 1.27 + def __init__(self): 1.28 + self.logfp = open(self.__class__.__name__ + '.csv', 'w') 1.29 + self.csv = csv.writer(self.logfp) 1.30 + 1.31 + def download(self): 1.32 + name = url[url.rfind('/')+1:] 1.33 + path = os.path.join(os.environ['HOME'], name) 1.34 + if not os.path.isfile(path): 1.35 + ofp = open(path + '.part', 'wb') 1.36 + try: 1.37 + ifp = urllib2.urlopen(url) 1.38 + nbytes = ifp.info()['content-length'] 1.39 + sys.stdout.write('%s: %s bytes ' % (name, nbytes)) 1.40 + sys.stdout.flush() 1.41 + while True: 1.42 + data = ifp.read(131072) 1.43 + if not data: break 1.44 + sys.stdout.write('.') 1.45 + sys.stdout.flush() 1.46 + ofp.write(data) 1.47 + del ofp 1.48 + os.rename(path + '.part', path) 1.49 + except: 1.50 + if os.path.exists(path + '.part'): 1.51 + os.unlink(path + '.part') 1.52 + if os.path.exists(path): 1.53 + os.unlink(path) 1.54 + raise 1.55 + return path 1.56 + 1.57 + def run(self, args, mustsucceed=True): 1.58 + ret = os.spawnvp(os.P_WAIT, args[0], args) 1.59 + if ret < 0: 1.60 + msg = 'killed by signal %d' % (-ret) 1.61 + if ret > 0: 1.62 + msg = 'exited with status %d' % (ret) 1.63 + if ret: 1.64 + if mustsucceed: 1.65 + raise CommandFailure('%s: %s' % (msg, ' '.join(args))) 1.66 + print >> sys.stderr, 'WARNING: %s: %s' % (msg, ' '.join(args)) 1.67 + 1.68 + def time(self, *args, **kwargs): 1.69 + start = time.time() 1.70 + self.run(*args, **kwargs) 1.71 + end = time.time() 1.72 + return end - start 1.73 + 1.74 + def logtime(self, name, elapsed, rest=[]): 1.75 + self.log('time:' + name, '%.3f' % elapsed, rest) 1.76 + 1.77 + def log(self, name, value, rest=[]): 1.78 + item = (name, value, repr(rest)) 1.79 + print ' '.join(item) 1.80 + self.csv.writerow(item) 1.81 + self.logfp.flush() 1.82 + 1.83 + def unpack(self): 1.84 + tarball = self.download() 1.85 + t = self.time(['tar', '-C', self.wdir, '-jxf', tarball]) 1.86 + self.logtime('internal:untar', t) 1.87 + for name in os.listdir(os.path.join(self.wdir, 'mozilla')): 1.88 + os.rename(os.path.join(self.wdir, 'mozilla', name), 1.89 + os.path.join(self.wdir, name)) 1.90 + 1.91 + def cleanup(self): 1.92 + pass 1.93 + 1.94 + def add(self, paths): 1.95 + pass 1.96 + 1.97 + def commit(self, msg, paths): 1.98 + pass 1.99 + 1.100 + def status(self, path): 1.101 + pass 1.102 + 1.103 + def remove(self, path): 1.104 + pass 1.105 + 1.106 + 1.107 +class subversion(rcs): 1.108 + def __init__(self, root): 1.109 + rcs.__init__(self) 1.110 + self.repo = os.path.join(root, 'repo') 1.111 + self.wdir = os.path.join(root, 'wc') 1.112 + create = self.time(['svnadmin', 'create', '--fs-type=fsfs', self.repo]) 1.113 + self.logtime('svn:create', create) 1.114 + co = self.time(['svn', 'co', 'file://' + self.repo, self.wdir]) 1.115 + self.logtime('svn:co', co) 1.116 + self.logtime('init', create + co) 1.117 + os.chdir(self.wdir) 1.118 + 1.119 + def dropmeta(self, names): 1.120 + return [n for n in names if os.path.basename(n) != '.svn'] 1.121 + 1.122 + def add(self, paths): 1.123 + t = self.time(['svn', 'add', '-q'] + paths) 1.124 + self.logtime('add %r' % paths, t) 1.125 + 1.126 + def commit(self, msg, paths=[]): 1.127 + if paths: 1.128 + t = self.time(['svn', 'ci', '-q', '-m', msg] + paths) 1.129 + else: 1.130 + t = self.time(['svn', 'ci', '-q', '-m', msg]) 1.131 + self.logtime('commit %r' % paths, t) 1.132 + 1.133 + 1.134 +class mercurial(rcs): 1.135 + def __init__(self, root): 1.136 + rcs.__init__(self) 1.137 + self.repo = os.path.join(root, 'repo') 1.138 + self.wdir = self.repo 1.139 + init = self.time(['hg', 'init', self.repo]) 1.140 + self.logtime('init', init) 1.141 + os.chdir(self.wdir) 1.142 + 1.143 + def dropmeta(self, names): 1.144 + return [n for n in names if os.path.basename(n) != '.hg'] 1.145 + 1.146 + def add(self, paths): 1.147 + t = self.time(['hg', 'add', '-q'] + paths) 1.148 + self.logtime('add %r' % paths, t) 1.149 + 1.150 + def commit(self, msg, paths=[]): 1.151 + if paths: 1.152 + t = self.time(['hg', 'ci', '-q', '-m', msg] + paths) 1.153 + else: 1.154 + t = self.time(['hg', 'ci', '-q', '-m', msg]) 1.155 + self.logtime('commit %r' % paths, t) 1.156 + 1.157 +def benchmark(cls): 1.158 + oldcwd = os.getcwd() 1.159 + root = tempfile.mkdtemp(prefix='sillybench.') 1.160 + try: 1.161 + print 'root', root 1.162 + inst = cls(root) 1.163 + inst.unpack() 1.164 + names = inst.dropmeta(os.listdir('.')) 1.165 + dirs = [n for n in names if os.path.isdir(n)] 1.166 + nondirs = [n for n in names if not os.path.isdir(n)] 1.167 + dirs.sort(key=hash) 1.168 + names.sort(key=hash) 1.169 + for d in dirs[:len(dirs)/2]: 1.170 + inst.add([d]) 1.171 + inst.commit('Add %r' % d, [d]) 1.172 + inst.add(dirs[len(dirs)/2:] + names) 1.173 + inst.commit('Add remaining dirs and files') 1.174 + finally: 1.175 + print >> sys.stderr, '[cleaning up...]' 1.176 + shutil.rmtree(root) 1.177 + os.chdir(oldcwd) 1.178 + 1.179 +benchmark(mercurial) 1.180 +#benchmark(subversion)