# # # patch "mtn_benchmark/benchmarks.py" # from [c4e1e7c4503221fd461f5796f54d99a309846df5] # to [eac99c9560e08ad74e48df5ec8e3821cc6691409] # # patch "mtn_benchmark/driver.py" # from [166389c362ec9c22019dc818580d9aaeed8b691c] # to [7c413d6c2f6ed9ce66eed22591636743a63b15e3] # # patch "mtn_benchmark/instrumenter.py" # from [db37331dcb3b7aedee7e35b00e7ad285e394b9be] # to [c04fd7417f6c9a34dfe9f064d78f514a884e6057] # # patch "mtn_benchmark/instrumenters.py" # from [ed7cb561de98eaffea72e7e92c5abede0c73ab71] # to [ea65e44ba430445b8ccc1dc4d56b9938f372df94] # # patch "mtn_benchmark/mtn.py" # from [fa50a6d6a4fa3c4cf880dc15b3aad40d212cccf4] # to [aa8fcab72d8ca83a372a68f0dcfac57eb10cfb51] # # patch "mtn_benchmark/speedtest.py" # from [046bbaefe0508e1f04da57193c4abc84e73b5363] # to [002dc3443137e5a619bfcec0319af4f8e59fb962] # ============================================================ --- mtn_benchmark/benchmarks.py c4e1e7c4503221fd461f5796f54d99a309846df5 +++ mtn_benchmark/benchmarks.py eac99c9560e08ad74e48df5ec8e3821cc6691409 @@ -1,3 +1,16 @@ +# This mock class documents what Benchmarks look like +class Benchmark(object): + def setup(self, testable): + # I am called from a special directory, which my run method will + # eventually be called in. + # I set up the directory in some useful way. + pass + + def run(self, testable): + # I am called in the directory that setup() previously ran in (or a + # copy of it). My testable may or may not be identical. + pass + class PullBenchmark(object): def __init__(self, repo_source): self.repo_source = repo_source ============================================================ --- mtn_benchmark/driver.py 166389c362ec9c22019dc818580d9aaeed8b691c +++ mtn_benchmark/driver.py 7c413d6c2f6ed9ce66eed22591636743a63b15e3 @@ -1,7 +1,9 @@ import random import os import os.path import shutil +from mtn_benchmark.util import ensure_dir +import mtn_benchmark.instrumenter as instrumenter class Driver(object): def __init__(self, scratch, results, testables, benchmarks, instrumenters, @@ -21,7 +23,7 @@ instrumenters = {} for testable_name, testable_f in self.testables.iteritems(): - testable = testable_f.new(Instrumenter("")) + testable = testable_f.new(instrumenter.InstrumenterObj("")) setupdir = os.path.join(benchdir, "setup-" + testable_name) ensure_dir(setupdir) os.chdir(setupdir) @@ -42,8 +44,8 @@ plan = self.testables.keys() random.shuffle(plan) for testable_name in plan: - instrumenter = instrumenters[testable_name] - testable = self.testables[testable_name].new(instrumenter) + instrumenter_obj = instrumenters[testable_name] + testable = self.testables[testable_name].new(instrumenter_obj) rundir = os.path.join(benchdir, "run-%s-%s-%s" % (testable_name, instrumenter_name, @@ -54,7 +56,7 @@ os.chdir(rundir) self.cache_clearer() benchmark_obj.run(testable) - instrumenter.flush() + instrumenter_obj.flush() if not self.debug: os.chdir(startdir) shutil.rmtree(rundir) ============================================================ --- mtn_benchmark/instrumenter.py db37331dcb3b7aedee7e35b00e7ad285e394b9be +++ mtn_benchmark/instrumenter.py c04fd7417f6c9a34dfe9f064d78f514a884e6057 @@ -1,8 +1,10 @@ import shutil import os import subprocess import csv +from mtn_benchmark.util import ensure_dir + class Process(object): # We stuff the called process into its own process group using the # preexec_fn hack. We need to do this so that we can clean up @@ -35,7 +37,7 @@ if self.popen is not None and self.popen.poll() is None: os.kill(self.popen.pid, 9) -class InstrumenterFactory(object): +class Instrumenter(object): def __init__(self, klass, repeats=1): self.klass = klass self.repeats = repeats @@ -43,7 +45,7 @@ def new(self, record_dir): return self.klass(record_dir) -class Instrumenter(object): +class InstrumenterObj(object): def __init__(self, record_dir): pass @@ -67,7 +69,7 @@ def flush(self): pass -class RecordingInstrumenter(Instrumenter): +class RecordingInstrumenterObj(InstrumenterObj): def __init__(self, record_dir): self.dir = record_dir ensure_dir(self.dir) ============================================================ --- mtn_benchmark/instrumenters.py ed7cb561de98eaffea72e7e92c5abede0c73ab71 +++ mtn_benchmark/instrumenters.py ea65e44ba430445b8ccc1dc4d56b9938f372df94 @@ -1,6 +1,9 @@ -import instrumenter +import mtn_benchmark.instrumenter as instrumenter -class TimingInstrumenter(instrumenter.RecordingInstrumenter): +def NullInstrumenter(): + return instrumenter.Instrumenter(instrumenter.InstrumenterObj, 1) + +class TimingInstrumenterObj(instrumenter.RecordingInstrumenterObj): def parse_time_str(self, s): # 1.7 -> 1.7 # 1:20.3 -> 80.3 @@ -25,8 +28,10 @@ self.record_stat(name + "-user-time", self.parse_time_str(user)) self.record_stat(name + "-system-time", self.parse_time_str(sys)) self.record_stat(name + "-wall-time", self.parse_time_str(wall)) - process = super(TimingInstrumenter, self).run_bg(name, my_cmd) + process = super(TimingInstrumenterObj, self).run_bg(name, my_cmd) process.hook(timing_hook) return process +def TimingInstrumenter(repeats=3): + return instrumenter.Instrumenter(TimingInstrumenterObj, repeats) ============================================================ --- mtn_benchmark/mtn.py fa50a6d6a4fa3c4cf880dc15b3aad40d212cccf4 +++ mtn_benchmark/mtn.py aa8fcab72d8ca83a372a68f0dcfac57eb10cfb51 @@ -1,3 +1,7 @@ +import os +import shutil +import time + # VCSes all have a factory, with method: .new(instrumenter) class Mtn(object): @@ -5,12 +9,12 @@ self.path = path def new(self, instrumenter): - return Mtn(self.path, instrumenter) + return InstrumentedMtn(self.path, instrumenter) # VCS objects are returned by this factory, and have a .setup() method, and so # far, .pull(source, target) and .init_repo(path) methods. -class MtnObj(object): +class InstrumentedMtn(object): def __init__(self, path, instrumenter): self.path = path self.instrumenter = instrumenter ============================================================ --- mtn_benchmark/speedtest.py 046bbaefe0508e1f04da57193c4abc84e73b5363 +++ mtn_benchmark/speedtest.py 002dc3443137e5a619bfcec0319af4f8e59fb962 @@ -1,33 +1,5 @@ -import os -import os.path - import shutil -import time -class Benchmark(object): - def setup(self, testable): - # I am called from a special directory, which my run method will - # eventually be called in. - # I set up the directory in some useful way. - pass - - def run(self, testable): - # I am called in the directory that setup() previously ran in (or a - # copy of it). My testable may or may not be identical. - pass - -class TestableFactory(object): - def new(self, instrumenter): - return Testable(instrumenter) - -class Testable(object): - def setup(self): - # like benchmark setup, but anything the VCS wants to do - pass - - def pull(self, name, repo, instrumenter): - pass - # each benchmark has a setup and a run # both are done in the same directory # and a directory to drop auxiliary results in @@ -69,21 +41,30 @@ # TODO: # figure out some consistent class/object/factory naming scheme +import mtn_benchmark.driver + +from mtn_benchmark.util import * +from mtn_benchmark.mtn import * +from mtn_benchmark.benchmarks import * +from mtn_benchmark.instrumenters import * +from mtn_benchmark.repo import * + def tryit(): scratch = "scratch" results = "results" shutil.rmtree(scratch, True) shutil.rmtree(results, True) - testables = {"mtn": MtnFactory("/home/njs/src/monotone/opt/mtn")} - benchmarks = {"pull": PullBenchmark(ExistingRepo("/home/njs/src/monotone/speedtest/t.db"))} - instrumenters = {"time": InstrumenterFactory(TimingInstrumenter, 2)} + testables = {"mtn": Mtn("/home/njs/src/monotone/opt/mtn")} + benchmarks = {"pull": PullBenchmark(ExistingRepo("/home/njs/src/monotone/benchmark/test.mtn"))} + instrumenters = {"time": TimingInstrumenter(2)} debug = 1 - cache_clearer = CacheClearer("./drop_caches") + cache_clearer = CacheClearer("/home/njs/src/monotone/benchmark/drop_caches") - driver = Driver(scratch, results, testables, benchmarks, instrumenters, - debug, cache_clearer) + driver = mtn_benchmark.driver.Driver(scratch, results, + testables, benchmarks, instrumenters, + debug, cache_clearer) driver.run() if __name__ == "__main__":