diff options
author | csilvers <csilvers@01de4be4-8c4a-0410-9132-4925637da917> | 2008-04-11 22:36:40 +0000 |
---|---|---|
committer | csilvers <csilvers@01de4be4-8c4a-0410-9132-4925637da917> | 2008-04-11 22:36:40 +0000 |
commit | 6b117b70f948dc72b107dab6d3e9ac99be297b6d (patch) | |
tree | 1726969de95d86fc5647af1eeb99ea0489ba91c4 /bench | |
parent | 204634dc3c7d4662fab0132140f1ac59e8c9312b (diff) | |
download | distcc-6b117b70f948dc72b107dab6d3e9ac99be297b6d.tar.gz |
The first step of moving everything in the distcc directory to the top
level. I'm doing this in two stages, because I don't understand svn
enough to be confident to do it in one. This first stage just copies
all the files from distcc/FOO to FOO. Now there are two copies of
each file under distcc; the Makefile/etc uses the one in distcc and
ignores the one at the top level.
The next commit will delete everything under distcc, and rewrite the
Makefile/etc to use the top-level versions instead.
git-svn-id: http://distcc.googlecode.com/svn/trunk@22 01de4be4-8c4a-0410-9132-4925637da917
Diffstat (limited to 'bench')
-rwxr-xr-x | bench/Build.py | 151 | ||||
-rwxr-xr-x | bench/Project.py | 114 | ||||
-rwxr-xr-x | bench/ProjectDefs.py | 114 | ||||
-rwxr-xr-x | bench/Summary.py | 76 | ||||
-rwxr-xr-x | bench/actions.py | 51 | ||||
-rwxr-xr-x | bench/benchmark.py | 176 | ||||
-rwxr-xr-x | bench/buildutil.py | 49 | ||||
-rwxr-xr-x | bench/compiler.py | 63 | ||||
-rwxr-xr-x | bench/statistics.py | 47 |
9 files changed, 841 insertions, 0 deletions
diff --git a/bench/Build.py b/bench/Build.py new file mode 100755 index 0000000..67d2817 --- /dev/null +++ b/bench/Build.py @@ -0,0 +1,151 @@ +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +from Project import Project +from compiler import CompilerSpec +import buildutil +from buildutil import make_dir, run_cmd, rm_files +import re, os, sys, time + + + +class Build: + """A Build is a combination of a Project and CompilerSpec. + + """ + def __init__(self, project, compiler, n_repeats): + self.project = project + self.compiler = compiler + self.n_repeats = n_repeats + + self.base_dir = os.path.join(os.getcwd(), "build", self.project.name, self.compiler.name) + self.unpacked_dir = os.path.join(self.base_dir, self.project.unpacked_subdir) + + # Some packages need to be started from a subdirectory of their + # unpacked form. For example, Samba is compiled from the "source/" + # subdirectory of the unpacked source. + if self.project.build_subdir: + self.build_dir = os.path.join(self.unpacked_dir, project.build_subdir) + else: + self.build_dir = self.unpacked_dir + + self.log_dir = self.build_dir + + def __repr__(self): + return "Build(%s, %s)" % (`self.project`, `self.compiler`) + + + def unpack(self): + """Unpack from source tarball into build directory""" + if re.search(r"\.tar\.bz2$", self.project.package_file): + tar_fmt = "tar xf %s --bzip2" + else: + tar_fmt = "tar xfz %s" + + tar_cmd = tar_fmt % os.path.join(os.getcwd(), self.project.package_dir, + self.project.package_file) + + make_dir(self.base_dir) + print "** Unpacking..." + run_cmd("cd %s && %s" % (self.base_dir, tar_cmd)) + + + def configure(self, compiler): + """Run configuration command for this tree, if any.""" + self.compiler = compiler + + make_dir(self.log_dir) + + configure_log = os.path.join(self.log_dir, "bench-configure.log") + distcc_log = os.path.join(self.log_dir, "bench-configure-distcc.log") + + rm_files((configure_log, distcc_log)) + + print "** Configuring..." + run_cmd("cd %s && \\\nDISTCC_LOG='%s' \\\nCC='%s' \\\nCXX='%s' \\\n%s \\\n>%s 2>&1" % + (self.build_dir, distcc_log, self.compiler.cc, + self.compiler.cxx, + self.project.configure_cmd, configure_log)) + + + def build(self, sum): + """Actually build the package.""" + + build_log = os.path.join(self.log_dir, "bench-build.log") + prebuild_log = os.path.join(self.log_dir, "bench-prebuild.log") + + distcc_log = os.path.join(self.log_dir, "bench-build-distcc.log") + + rm_files((build_log, distcc_log)) + + print "** Building..." + if self.project.pre_build_cmd: + cmd = ("cd %s && %s > %s 2>&1" % (self.build_dir, + self.project.pre_build_cmd, + prebuild_log)) + run_cmd(cmd) + + cmd = ("cd %s && \\\n%s \\\nDISTCC_LOG='%s' \\\nCC='%s' \\\nCXX='%s' \\\n%s \\\n>%s 2>&1" % + (self.build_dir, self.project.build_cmd, distcc_log, + self.compiler.cc, + self.compiler.cxx, + self.compiler.make_opts, + build_log)) + result, elapsed = run_cmd(cmd) + return elapsed + + + def clean(self): + clean_log = os.path.join(self.log_dir, "bench-clean.log") + print "** Cleaning build directory" + cmd = "cd %s && make clean >%s 2>&1" % (self.build_dir, clean_log) + run_cmd(cmd) + + + def scrub(self): + print "** Removing build directory" + run_cmd("rm -rf %s" % self.unpacked_dir) + + + def build_actions(self, actions, summary): + """Carry out selected actions. + + Catch exceptions and handle.""" + try: + times = [] + if 'sweep' in actions: + self.scrub() + if 'unpack' in actions: + self.unpack() + if 'configure' in actions: + self.configure(self.compiler) + for i in range(self.n_repeats): + if 'build' in actions: + times.append(self.build(summary)) + if 'clean' in actions: + self.clean() + if 'scrub' in actions: + self.scrub() + summary.store(self.project, self.compiler, times) + except KeyboardInterrupt: + raise + except: + apply(sys.excepthook, sys.exc_info()) # print traceback + summary.store(self.project, self.compiler, 'FAIL') diff --git a/bench/Project.py b/bench/Project.py new file mode 100755 index 0000000..9551917 --- /dev/null +++ b/bench/Project.py @@ -0,0 +1,114 @@ +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +import re, os, sys, time +from buildutil import make_dir, run_cmd + + +# Trees of software to be built. +trees = { } + + +class Project: + """Defines a project to be built and tested. + + The Python process remains in the top-level directory for the + whole process. Commands are kicked off in subdirectories if + necessary. + + 'subdir' variables give just a single component of a name; 'dir' variables + give a full path.""" + + def __init__(self, url, package_file=None, + md5=None, + name=None, + configure_cmd=None, + pre_build_cmd = None, + build_cmd=None, + unpacked_subdir=None, + build_subdir=None, + source_name=None): + self.url = url + if not package_file: + package_file = url.split('/')[-1] + self.package_file = package_file + + if not name: + name = re.match(r"(.*)\.tar(\.gz|\.bz2|)$", package_file).group(1) + self.name = name + + self.md5 = md5 + + self.configure_cmd = configure_cmd or "./configure" + self.build_cmd = build_cmd or "make" + self.source_name = source_name or name + self.pre_build_cmd = pre_build_cmd + + self.package_dir = "packages" + self.download_dir = "download" + + # By default, we assume the package creates an unpacked + # directory whose name is the same as the tarball. For + # example, Wine's tarball is "Wine-xxxxxxx", but it unpacks to + # "wine-xxxxxxxx". + self.unpacked_subdir = unpacked_subdir or self.source_name + self.build_subdir = build_subdir + + + def register(self): + trees[self.name] = self + + + def __repr__(self): + return "Project(name=%s)" % `self.name` + + + def download(self): + """Download package from vendor site""" + + make_dir(self.package_dir) + make_dir(self.download_dir) + + if not os.path.isfile(os.path.join(self.package_dir, self.package_file)): + # XXX: snarf gets upset if the HTTP server returns "416 + # Requested Range Not Satisfiable" because the file is already + # totally downloaded. This is kind of a snarf bug. + print "** Downloading" + run_cmd("cd %s && wget --continue %s" % + (self.download_dir, self.url)) + run_cmd("mv %s %s" % + (os.path.join(self.download_dir, self.package_file), + self.package_dir)) + + def md5check(self): + if self.md5: + print "** Checking source package integrity" + run_cmd("cd %s && echo '%s' | md5sum -c /dev/stdin" % + (self.package_dir, self.md5)) + + + def pre_actions(self, actions): + """Perform actions preparatory to building according to selection.""" + + if 'download' in actions: + self.download() + if 'md5check' in actions: + self.md5check() + diff --git a/bench/ProjectDefs.py b/bench/ProjectDefs.py new file mode 100755 index 0000000..0d188a8 --- /dev/null +++ b/bench/ProjectDefs.py @@ -0,0 +1,114 @@ +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003, 2004 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +__doc__ = """distcc benchmark project definitions""" + +from Project import Project + +# Would like to test glibc, but it needs a separate source and build +# directory, and this tool doesn't support that yet. + +# disable-sanity-checks is needed to stop it wanting linuxthreads -- +# the resulting library is useless, but this is only a test. + +#Project(url = 'http://ftp.gnu.org/pub/gnu/glibc/glibc-2.3.2.tar.bz2', +# configure_cmd = './configure --disable-sanity-checks' +# ).register() + +#Project(url='http://mirror.aarnet.edu.au/pub/gnu/libc/glibc-2.3.tar.bz2', +# configure_cmd='./configure --disable-sanity-checks', +# md5='fd20b4a9feeb2b2f0f589b1a9ae8a5e2 glibc-2.3.tar.bz2').register() + +Project(url='http://archive.apache.org/dist/httpd/httpd-2.0.43.tar.gz', + md5='8051de5d160c43d4ed2cc47dc9be6fd3 httpd-2.0.43.tar.gz').register() + +Project(url='ftp://ftp.gtk.org/pub/gtk/v2.0/glib-2.0.7.tar.bz2', + md5='5882b1e729f57cb18af653a2f504197b glib-2.0.7.tar.bz2').register() + +Project(url='http://us1.samba.org/samba/ftp/old-versions/samba-2.2.7.tar.gz', + build_subdir='source', + md5='824cd4e305f9b744f3eec702a7b96f7f samba-2.2.7.tar.gz', + ).register() + +Project(url='http://ftp.gnu.org/gnu/make/make-3.80.tar.bz2', + md5='0bbd1df101bc0294d440471e50feca71 *make-3.80.tar.bz2' + ).register() + +# failed: "make: *** No rule to make target `defconfig'. Stop." +#Project(url='http://public.ftp.planetmirror.com/pub/linux/kernel/v2.4/linux-2.4.20.tar.bz2', +# configure_cmd='make defconfig', +# build_cmd='make bzImage', +# ).register() + +Project(url='http://www.kernel.org/pub/linux/kernel/v2.5/linux-2.5.51.tar.bz2', + md5='2300b7b7d2ce4c017fe6dae49717fd9a *linux-2.5.51.tar.bz2', + configure_cmd='make defconfig', + build_cmd='make bzImage' + ).register() + +Project(url='http://sources-redhat.oc1.mirrors.redwire.net/gdb/old-releases/gdb-5.3.tar.gz', + ).register() + +## gimp 1.2.3 has makefile bugs that break -j +## Project(url='ftp://212.8.35.65/pub/FreeBSD/distfiles/gimp-1.2.3.tar.bz2', +## md5='b19235f19f524f772a4aef597a69b1da *gimp-1.2.3.tar.bz2', +## configure_cmd='./configure --disable-perl', +## ).register() + +Project(url='ftp://ftp.gimp.org/pub/gimp/v2.2/gimp-2.2.10.tar.bz2', + md5='aa29506ed2272af02941a7a601a7a097 gimp-2.2.10.tar.bz2', + configure_cmd='./configure --disable-perl --disable-print', + ).register() + +## Project(url='http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.3.tar.bz2', +## ).register() + +Project(url='http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.4.tar.bz2', + md5='73205d83a5612a43441a8532683c0434 wine-0.9.4.tar.bz2', + ).register() + +Project(url='http://public.planetmirror.com.au/pub/gnu/hello/hello-2.1.1.tar.gz', + md5='70c9ccf9fac07f762c24f2df2290784d *hello-2.1.1.tar.gz', + ).register() + + +# XXX: Does not build on Debian at the moment, problem with libIDL-config + +# Project(url='http://mirror.aarnet.edu.au/pub/mozilla/releases/mozilla1.4/src/mozilla-source-1.4.tar.bz2', +# name='mozilla-1.4', +# configure_cmd="LIBIDL_CONFIG=libIDL-config-2 ./configure", +# unpacked_subdir='mozilla', +# ).register() + + +Project(url='http://ftp.mozilla.org/pub/firebird/releases/0.6/MozillaFirebird-0.6-source.tar.bz2', + name='MozillaFirebird', + unpacked_subdir='mozilla', + ).register() + +Project(url='http://us1.samba.org/samba/ftp/old-versions/samba-3.0.20.tar.gz', + name='samba-3.0.20', + build_subdir='source', + # newer versions of popt can be incompatible + configure_cmd='./configure --with-included-popt', + pre_build_cmd = 'make proto', + ).register() + + diff --git a/bench/Summary.py b/bench/Summary.py new file mode 100755 index 0000000..33c8111 --- /dev/null +++ b/bench/Summary.py @@ -0,0 +1,76 @@ +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +class Summary: + """Stores and prints results of building different things""" + + # Table is a sequence, because we prefer to have things printed + # out in the order they were executed. + + def __init__(self): + self._table = [] + + def store(self, project, compiler, elapsed_times): + """ + elapsed_times is a sequence of elapsed times to build the project. + A sequence because we can build projects repeatedly. + """ + self._table.append((project.name, compiler.name, elapsed_times)) + + def print_raw(self): + from pprint import pprint + pprint(self._table) + + def print_table(self): + import time, os, sys + import statistics + + # if nothing was run, skip it + if not len(self._table): + return + + """Print out in a nice tabular form""" + print """ + ======================== + distcc benchmark results + ======================== + +""" + print "Date: ", time.ctime() + print "DISTCC_HOSTS: %s" % `os.getenv('DISTCC_HOSTS')` + sys.stdout.flush() + os.system("uname -a") + + print "%-20s %-30s %8s %8s" % ('project', 'compiler', 'time', 's.d.') + + for row in self._table: + print "%-20s %-30s " % row[:2], + times = row[2] + if times == 'FAIL': + print '%9s' % 'FAIL' + else: + mean = statistics.mean(times) + sd = statistics.std(times) + print "%8.4fs" % mean, + if sd is None: + print "%9s" % "n/a" + else: + print "%8.4fs" % sd + diff --git a/bench/actions.py b/bench/actions.py new file mode 100755 index 0000000..d6c3544 --- /dev/null +++ b/bench/actions.py @@ -0,0 +1,51 @@ +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +# Tuples of (name, default, descr) +all_actions = [('download', True, ''), + ('md5check', True, 'check file was downloaded correctly'), + ('sweep', True, 'remove build directory before unpacking'), + ('unpack', True, 'unpack source'), + ('configure', True, ''), + ('clean', True, 'run "make clean" or equivalent'), + ('build', True, ''), + ('scrub', True, 'remove build directory')] + + +def action_help(): + print "Actions:" + for action, default, descr in all_actions: + default_ch = default and '*' or ' ' + print " %c %-20s %s" % (default_ch, action, descr) + print " (* = on by default)" + + +# Filter out only actions where 'default' is true +default_actions = [a[0] for a in all_actions if a[1]] + + +def parse_opt_actions(optarg): + import sys + opt_actions = optarg.split(',') + action_names = [a[0] for a in all_actions] + for oa in opt_actions: + if oa not in action_names: + raise ValueError, ("no such action: %s" % `oa`) + return opt_actions diff --git a/bench/benchmark.py b/bench/benchmark.py new file mode 100755 index 0000000..a4f80b3 --- /dev/null +++ b/bench/benchmark.py @@ -0,0 +1,176 @@ +#! /usr/bin/python + +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003, 2004 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + + +# Unlike the main distcc test suite, this program *does* require you +# to manually set up servers on your choice of machines on the +# network, and make sure that they all have appropriate compilers +# installed. The performance measurements obviously depend on the +# network and hardware available. + +# It also depends on you having the necessary dependencies to build +# the software. If you regularly build software on Linux you should +# be OK. Some things (the GIMP) will be harder than others. + +# On some platforms, it may be impossible to build some targets -- for +# example, Linux depends on having a real-mode x86 assembler, which +# probably isn't installed on Solaris. + +# Note that running this program will potentially download many +# megabytes of test data. + + +# TODO: Support applying patches after unpacking, before building. +# For example, they might be needed to fix -j bugs in the Makefile. + +# TODO: In stats, show ratio of build time to slowest build time. (Or +# to first one run?) + +# TODO: Allow choice of which compiler and make options to use. + +# TODO: Try building something large in C++. + +# TODO: Set CXX as well. + +# TODO: Add option to run tests repeatedly and show mean and std. dev. + +# TODO: Perhaps add option to do "make clean" -- this might be faster +# than unzipping and configuring every time. But perhaps also less +# reproducible. + +# TODO: Add option to run tests on different sets or orderings of +# machines. + + +import re, os, sys, time +from getopt import getopt + +from Summary import Summary +from Project import Project, trees +from compiler import CompilerSpec +from Build import Build +import actions, compiler + +import ProjectDefs # this adds a lot of definitions to 'trees' + + +def error(msg): + sys.stderr.write(msg + "\n") + + +def list_projects(): + names = trees.keys() + names.sort() + for n in names: + print n + + +def find_project(name): + """ + Return the nearest unique match for name. + """ + best_match = None + for pn in trees.keys(): + if pn.startswith(name): + if best_match: + raise ValueError, "ambiguous prefix %s" % name + else: + best_match = pn + + if not best_match: + raise ValueError, "nothing matches %s" % name + else: + return trees[best_match] + + + +def show_help(): + print """Usage: benchmark.py [OPTION]... [PROJECT]... +Test distcc relative performance building different projects. +By default, all known projects are built. + +Options: + --help show brief help message + --list-projects show defined projects + -c, --compiler=COMPILER specify one compiler to use + -n N repeat compilation N times + -a, --actions=ACTIONS comma-separated list of action phases + to perform + +Compilers can be specified as either "local,N" to run N copies of gcc, +or dist,N to run N copies of distcc. Multiple -c options specify +different scenarios to measure. The default is to run a nonparallel +local compile and a parallel distributed compile. +""" +actions.action_help() + + +# -a is for developer use only and not documented; unless you're +# careful the results will just be confusing. + + + + +###################################################################### +def main(): + """Run the benchmark per arguments""" + sum = Summary() + options, args = getopt(sys.argv[1:], 'a:c:n:', + ['list-projects', 'actions=', 'help', 'compiler=']) + opt_actions = actions.default_actions + set_compilers = [] + opt_repeats = 1 + + for opt, optarg in options: + if opt == '--help': + show_help() + return + elif opt == '--list-projects': + list_projects() + return + elif opt == '--actions' or opt == '-a': + opt_actions = actions.parse_opt_actions(optarg) + elif opt == '--compiler' or opt == '-c': + set_compilers.append(compiler.parse_opt(optarg)) + elif opt == '-n': + opt_repeats = int(optarg) + + if not set_compilers: + set_compilers = compiler.default_compilers() + + # Find named projects, or run all by default + if args: + chosen_projects = [find_project(name) for name in args] + else: + chosen_projects = trees.values() + + for proj in chosen_projects: + proj.pre_actions(opt_actions) + for comp in set_compilers: + build = Build(proj, comp, opt_repeats) + build.build_actions(opt_actions, sum) + + sum.print_table() + +if __name__ == '__main__': + main() + diff --git a/bench/buildutil.py b/bench/buildutil.py new file mode 100755 index 0000000..8a43353 --- /dev/null +++ b/bench/buildutil.py @@ -0,0 +1,49 @@ +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + + +def make_dir(d): + import os + if not os.path.isdir(d): + os.makedirs(d) + + +def run_cmd(cmd, expected=0): + import time, os + + before = time.time() + print '%% %s' % cmd + result = os.system(cmd) + after = time.time() + elapsed = (after - before) + print '%16.4fs elapsed\n' % elapsed + if expected is not None: + if expected != result: + raise AssertionError("command failed: expected status %d, got %d", + expected, result) + return result, elapsed + + +def rm_files(file_list): + import os + for f in file_list: + if os.path.exists(f): + os.unlink(f) + diff --git a/bench/compiler.py b/bench/compiler.py new file mode 100755 index 0000000..3cc9d1d --- /dev/null +++ b/bench/compiler.py @@ -0,0 +1,63 @@ +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2002, 2003 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +class CompilerSpec: + """Describes a compiler/make setup. + + Used to define different situations such as local compilation, and + various degrees of parallelism.""" + + def __init__(self, cc=None, cxx=None, make_opts=None, name=None): + self.cc = cc or 'gcc' + self.cxx = cxx or 'c++' + self.make_opts = make_opts or '' + self.name = name or (self.cc + "__" + self.make_opts).replace(' ', '_') + + +def default_compilers(): + return [parse_opt('local,1'), + parse_opt('dist,8'), + ] + +def parse_opt(optarg): + """Parse command-line specification of a compiler + + XXX: I don't really know what the best syntax for this is. For + the moment, it is "local" or "dist", followed by a comma and a + -j number. Perhaps we need to be able to specify host lists here + too. + """ + where, howmany = optarg.split(',') + howmany = int(howmany) + if where == 'local': + return CompilerSpec(name='local_%02d' % howmany, + cc='cc', + cxx='c++', + make_opts='-j%d' % howmany) + elif where == 'dist': + return CompilerSpec(name='dist_%02d' % howmany, + cxx='distcc c++', + cc='distcc cc', + make_opts='-j%d' % howmany) + else: + raise ValueError, ("don't understand %s" % `where`) + + + diff --git a/bench/statistics.py b/bench/statistics.py new file mode 100755 index 0000000..1565752 --- /dev/null +++ b/bench/statistics.py @@ -0,0 +1,47 @@ +#! /usr/bin/env python2.2 + +# distcc/benchmark -- automated system for testing distcc correctness +# and performance on various source trees. + +# Copyright (C) 2003 by Martin Pool + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + + +# Based in part on http://starship.python.net/crew/jhauser/NumAdd.py.html by Janko Hauser + + +import Numeric + +def var(m): + """ + Variance of m. + """ + if len(m) < 2: + return None + mu = Numeric.average(m) + return (Numeric.add.reduce(Numeric.power(Numeric.ravel(m)-mu, 2)) + / (len(m)-1.)) + +def std(m): + """ + Standard deviation of m. + """ + v = var(m) + return v and Numeric.sqrt(v) + +def mean(m): + return Numeric.average(m) |