# Copyright (c) 2001 Autonomous Zone Industries # Copyright (c) 2002-2007 Bryce "Zooko" Wilcox-O'Hearn # This file is licensed under the # GNU Lesser General Public License v2.1. # See the file COPYING or visit http://www.gnu.org/ for details. """ Benchmark a function for its behavior with respect to N... """ import math, operator, sys, time if not hasattr(time, "realtime"): time.realtime = time.time from assertutil import _assert def makeg(func): def blah(n, func=func): for i in xrange(n): func() return blah def rep_bench(func, n, initfunc=None, MAXREPS=5, MAXTIME=60.0): """ Will run the func up to MAXREPS times, but won't start a new run if MAXTIME (wall-clock time) has already elapsed (unless MAXTIME is None). """ starttime = time.realtime() print "N: %7d," % n, sys.stdout.flush() scores = [] while ((len(scores) < MAXREPS) or (MAXREPS is None)) and ((MAXTIME is None) or ((time.realtime() - starttime) < MAXTIME)): if initfunc: initfunc(n) tl = bench_it(func, n) if tl < 0: raise AssertionError(tl) scores.append(tl) sum = reduce(operator.__add__, scores) ave = sum / len(scores) scores.sort() nw = min(int(math.log(len(scores)))+1, len(scores)) worst = scores[-nw] best = scores[nw-1] if ave == 0: print "time: ave: %7.2f, %3dth-best: %7.2f, %3dth-worst: %7.2f (of %6d), ave rate: N/A" % (ave, nw, best, nw, worst, len(scores),) else: print "time: ave: %7.2f, %3dth-best: %7.2f, %3dth-worst: %7.2f (of %6d), reps/s: %6d, averate: %8.0f" % (ave, nw, best, nw, worst, len(scores), len(scores) / sum, (n * len(scores)) / sum,) MARGINOFERROR = 10 worstemptymeasure = 0 def bench_it(func, n): st = time.realtime() func(n) sto = time.realtime() timeelapsed = sto - st global worstemptymeasure emsta = time.realtime() emstop = time.realtime() empty = emstop - emsta if empty > worstemptymeasure: worstemptymeasure = empty _assert(timeelapsed*MARGINOFERROR > worstemptymeasure, "Invoking func %s(%s) took only %0.20f seconds, but we cannot accurately measure times much less than %0.20f seconds. Therefore we cannot produce good results here. Try benchmarking a more time-consuming variant." % (func, n, timeelapsed, worstemptymeasure,)) return timeelapsed def bench(func, initfunc=None, TOPXP=21, MAXREPS=5, MAXTIME=60.0): BSIZES = [] for i in range(TOPXP-6, TOPXP+1, 2): BSIZES.append(2 ** i) for BSIZE in BSIZES: rep_bench(func, BSIZE, initfunc=initfunc, MAXREPS=MAXREPS, MAXTIME=MAXTIME)