""" Downloaded from https://code.google.com/p/benchrun/ A benchmark is defined by creating a subclass of Benchmark. The subclass should define a method run() that executes the code to be timed and returns the elapsed time in seconds (as a float), or None if the benchmark should be skipped. See fibonacci.py for example. """ import sys if sys.platform == 'win32': from time import clock # pylint: disable=no-name-in-module,unused-import else: from time import time as clock # pylint: disable=unused-import # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/302478 def combinations(*seqin): def rloop(seqin, comb): if seqin: for item in seqin[0]: newcomb = comb + [item] for item2 in rloop(seqin[1:], newcomb): yield item2 else: yield comb return rloop(seqin, []) class Benchmark: sort_by = [] reference = None parameters = {} def __init__(self): self.pnames = [] self.pvalues = [] self.results = [] self.results_dict = {} for pname in self.parameters: value = getattr(self, pname) self.pnames.append(pname) self.pvalues.append(value) self.pcombos = list(combinations(*self.pvalues)) if self.reference: # pylint: disable=unsubscriptable-object self.reference_param = self.reference[0] self.reference_value = self.reference[1] def time_all(self): """Run benchmark for all versions and parameters.""" for params in self.pcombos: args = dict(zip(self.pnames, params)) # pylint: disable=no-member t = self.run(**args) self.results.append(tuple(params) + (t,)) self.results_dict[tuple(params)] = t def sort_results(self): sort_keys = [] for name in self.sort_by: sort_keys += [self.pnames.index(name)] for i, name in enumerate(self.pnames): if i not in sort_keys: sort_keys += [i] def key(v): return list(v[i] for i in sort_keys) self.results.sort(key=key) def get_factor(self, pvalues, time): if not self.reference or not time: return None pvalues = list(pvalues) i = self.pnames.index(self.reference_param) if pvalues[i] == self.reference_value: return None pvalues[i] = self.reference_value ref = self.results_dict[tuple(pvalues)] if ref is None: return None return ref / time def print_result(self): """Run benchmark for all versions and parameters and print results in tabular form to the standard output.""" self.time_all() self.sort_results() print("=" * 78) print() print(self.__class__.__name__) print(self.__doc__ + "\n") colwidth = 15 ts = "seconds" if self.reference: ts += " (x faster than " + (str(self.reference_value)) + ")" print(" " + " ".join([str(r).ljust(colwidth) for r in self.pnames + [ts]])) print("-" * 79) for vals in self.results: pvalues = vals[:-1] time = vals[-1] if time is None: stime = "(n/a)" else: stime = "%.8f" % time factor = self.get_factor(pvalues, time) if factor is not None: stime += (" (%.2f)" % factor) vals = pvalues + (stime,) row = [str(val).ljust(colwidth) for val in vals] print(" " + " ".join(row)) print()