diff -r aea58e1cae75 Doc/library/timeit.rst --- a/Doc/library/timeit.rst Sun Sep 08 14:14:38 2013 +0200 +++ b/Doc/library/timeit.rst Sun Sep 08 16:53:44 2013 +0100 @@ -29,11 +29,11 @@ .. code-block:: sh $ python -m timeit '"-".join(str(n) for n in range(100))' - 10000 loops, best of 3: 40.3 usec per loop + 10,000 loops, best of 3: 34.6 usec per loop, 28,870.783/s $ python -m timeit '"-".join([str(n) for n in range(100)])' - 10000 loops, best of 3: 33.4 usec per loop + 10,000 loops, best of 3: 31 usec per loop, 32,278.392/s $ python -m timeit '"-".join(map(str, range(100)))' - 10000 loops, best of 3: 25.2 usec per loop + 10,000 loops, best of 3: 25.6 usec per loop, 39,128.484/s This can be achieved from the :ref:`python-interface` with:: @@ -239,9 +239,9 @@ .. code-block:: sh $ python -m timeit -s 'text = "sample string"; char = "g"' 'char in text' - 10000000 loops, best of 3: 0.0877 usec per loop + 10,000,000 loops, best of 3: 0.0574 usec per loop, 17,415,738.020/s $ python -m timeit -s 'text = "sample string"; char = "g"' 'text.find(char)' - 1000000 loops, best of 3: 0.342 usec per loop + 1,000,000 loops, best of 3: 0.225 usec per loop, 4,440,226.977/s :: @@ -268,14 +268,14 @@ .. code-block:: sh $ python -m timeit 'try:' ' str.__bool__' 'except AttributeError:' ' pass' - 100000 loops, best of 3: 15.7 usec per loop + 1,000,000 loops, best of 3: 0.701 usec per loop, 1,425,528.038/s $ python -m timeit 'if hasattr(str, "__bool__"): pass' - 100000 loops, best of 3: 4.26 usec per loop + 1,000,000 loops, best of 3: 0.529 usec per loop, 1,890,741.076/s $ python -m timeit 'try:' ' int.__bool__' 'except AttributeError:' ' pass' - 1000000 loops, best of 3: 1.43 usec per loop + 10,000,000 loops, best of 3: 0.0689 usec per loop, 14,522,881.609/s $ python -m timeit 'if hasattr(int, "__bool__"): pass' - 100000 loops, best of 3: 2.23 usec per loop + 10,000,000 loops, best of 3: 0.154 usec per loop, 6,497,353.556/s :: diff -r aea58e1cae75 Lib/timeit.py --- a/Lib/timeit.py Sun Sep 08 14:14:38 2013 +0200 +++ b/Lib/timeit.py Sun Sep 08 16:53:44 2013 +0100 @@ -73,10 +73,12 @@ return _t1 - _t0 """ + def reindent(src, indent): """Helper to reindent a multi-line statement.""" return src.replace("\n", "\n" + " "*indent) + def _template_func(setup, func): """Create a timer function. Used if the "statement" is a callable.""" def inner(_it, _timer, _func=func): @@ -88,7 +90,9 @@ return _t1 - _t0 return inner + class Timer: + """Class for timing execution speed of small code snippets. The constructor takes a statement to be timed, an additional @@ -118,7 +122,7 @@ ns['_setup'] = setup else: raise ValueError("setup is neither a string nor callable") - self.src = src # Save for traceback display + self.src = src # Save for traceback display code = compile(src, dummy_src_name, "exec") exec(code, globals(), ns) self.inner = ns["inner"] @@ -126,6 +130,7 @@ self.src = None if isinstance(setup, str): _setup = setup + def setup(): exec(_setup, globals(), ns) elif not callable(setup): @@ -151,7 +156,8 @@ The optional file argument directs where the traceback is sent; it defaults to sys.stderr. """ - import linecache, traceback + import linecache + import traceback if self.src is not None: linecache.cache[dummy_src_name] = (len(self.src), None, @@ -207,16 +213,19 @@ r.append(t) return r + def timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number): """Convenience function to create Timer object and call timeit method.""" return Timer(stmt, setup, timer).timeit(number) + def repeat(stmt="pass", setup="pass", timer=default_timer, repeat=default_repeat, number=default_number): """Convenience function to create Timer object and call repeat method.""" return Timer(stmt, setup, timer).repeat(repeat, number) + def main(args=None, *, _wrap_timer=None): """Main program, used when run as a script. @@ -248,7 +257,7 @@ return 2 timer = default_timer stmt = "\n".join(args) or "pass" - number = 0 # auto-determine + number = 0 # auto-determine setup = [] repeat = default_repeat verbose = 0 @@ -287,7 +296,7 @@ if number == 0: # determine number so that 0.2 <= total time < 2.0 for i in range(1, 10): - number = 10**i + number = 10 ** i try: x = t.timeit(number) except: @@ -305,17 +314,21 @@ best = min(r) if verbose: print("raw times:", " ".join(["%.*g" % (precision, x) for x in r])) - print("%d loops," % number, end=' ') - usec = best * 1e6 / number - if usec < 1000: - print("best of %d: %.*g usec per loop" % (repeat, precision, usec)) - else: - msec = usec / 1000 - if msec < 1000: - print("best of %d: %.*g msec per loop" % (repeat, precision, msec)) - else: - sec = msec / 1000 - print("best of %d: %.*g sec per loop" % (repeat, precision, sec)) + + sec = best / number + duration = sec * 1e6 + unit = 'usec' + + if duration >= 1000: + unit = 'msec' + duration /= 1000 + + if duration >= 1000: + unit = 'sec' + duration /= 1000 + + print("{0:,} loops, best of {1}: {2:.{precision}g} {3} per loop, {4:,.{precision}f}/s".format( + number, repeat, duration, unit, 1 / sec, precision=precision)) return None if __name__ == "__main__":