import math import time import timeit import platform import sys try: from time import monotonic as timeout_time except ImportError: timeout_time = time.time def compute_precision(func): precision = None points = 0 timeout = timeout_time() + 1.0 previous = func() while timeout_time() < timeout or points < 3: for loop in range(10): t1 = func() t2 = func() dt = t2 - t1 if 0 < dt: break else: dt = t2 - previous if dt <= 0.0: continue if precision is not None: precision = min(precision, dt) else: precision = dt points += 1 previous = func() return precision class Benchmark: def __init__(self, timer=None): if timer is None: timer = time.time self.timer = timer self.timer_precision = None self.time_unit = ("ns", 1e-9) self.min_time = 0.1 self.max_time = 1.0 self.min_repeat = 5 #self.max_repeat = 1000 self.max_repeat = None def format_delta(self, dt): if dt >= 1.0: return "%.3g sec" % (dt,) elif dt >= 1e-3: return "%.3g ms" % (dt * 1e3,) elif dt >= 1e-6: return "%.3g ms" % (dt * 1e6,) else: return "%.0f ns" % (dt * 1e9,) def run(self, stmt="pass", setup="pass", msg=None): if msg is None: if setup != "pass": msg = "%s; %s" % (setup, stmt) else: msg = stmt timer = timeit.Timer(stmt=stmt, setup=setup, timer=self.timer) # Calibrate the number of loops if self.min_time < 1.0: if self.timer_precision is None: self.timer_precision = compute_precision(self.timer) print("Clock precision = %s" % self.format_delta(self.timer_precision)) min_time = max(self.min_time, self.timer_precision * 100) min_time_estimate = max(self.min_time / 100, self.timer_precision * 10) else: min_time = self.min_time min_time_estimate = self.min_time / 100 loops = 1 estimate = False min_progress = 1.0 while True: dt = timer.timeit(number=loops) best = dt / loops if dt / min_time >= min_progress: break # coarse estimation of the number of loops if not estimate and dt >= min_time_estimate: estimate = True old = loops loops = max(int(min_time / best), loops * 2) min_progress = 0.75 else: loops *= 10 # Choose how many time we must repeat the test repeat = int(math.ceil(self.max_time / dt)) if self.max_repeat is not None: repeat = min(repeat, self.max_repeat) repeat = max(repeat, self.min_repeat) if 1 < repeat: # Repeat the benchmark best_repeat = min(timer.repeat(repeat=(repeat - 1), number=loops)) best = min(best, best_repeat / loops) best = self.format_delta(best) print("% 5s: %s" % (best, msg)) def dump_cpu_frequency(): import struct bits = struct.calcsize("L") * 8 print("OS %s bits" % bits) try: cpuinfo = open("/proc/cpuinfo") except IOError: return with cpuinfo: for line in cpuinfo: if line.startswith('model name'): model = line.split(':', 1)[-1].strip() print(model) break def main(): print(sys.version.splitlines()[0]) print(platform.platform()) bench = Benchmark() bench.run(setup='N=200; fmt="{0}-"*N; arg="abc"', stmt='fmt.format(arg)') bench.run( setup='N=200; L=3; fmt="%s"*N; args=("a"*L,)*N', stmt='fmt % args') bench.run( setup='s="The {k1} is {k2} the {k3}."; args={"k1": "x", "k2": "y", "k3": "z"}', stmt='s.format(**args)') bench.run( setup='s="The %(k1)s is %(k2)s the %(k3)s."; args={"k1":"x","k2":"y","k3":"z",}', stmt='s%args') bench.run( setup='s="x={}, y={}, z={}"; args=(123, 456, 789)', stmt='s.format(*args)') bench.run( setup='s="x=%s, y=%u, z=%x"; args=(123, 456, 789)', stmt='s%args') if 1: for setup in ( 'fmt="{}"; arg="abc"', 'fmt="{}"; arg=123', 'fmt="x={}"; arg="abc"', 'fmt="x={}"; arg=123', ): bench.run(setup=setup, stmt='fmt.format(arg)') if 1: bench.run('str(12345)') for s in ('', 'A', '\u0080', '\u0100', '\U00010000'): bench.run('%a.format(12345)' % (s + '{}',)) for s in ('', 'A', '\u0080', '\u0100', '\U00010000'): bench.run('%a.format(12345)' % (s + '{:-10}',)) for s in ('', 'A', '\u0080', '\u0100', '\U00010000'): bench.run('%a.format(12345)' % (s + '{:,}',)) if 1: bench.run( setup='fmt="%s"; arg="abc"', stmt='fmt % arg') bench.run( setup='fmt="%s"; arg=123', stmt='fmt % arg') bench.run( setup='fmt="%s:"; arg="abc"', stmt='fmt % arg') dump_cpu_frequency() if __name__ == "__main__": main()