# HG changeset patch # User Bryan O'Sullivan # Date 2013-02-28 21:11:42 # Node ID af9ddea2cb99b6e4314a6e79b793b5fc30ea4f19 # Parent 716cad9306914703d27cc3468036fdba4412ee90 util: add a timed function for use during development I often want to measure the cost of a function call before/after an optimization, where using top level "hg --time" timing introduces enough other noise that I can't tell if my efforts are having an effect. This decorator allows a developer to measure a function's cost with finer granularity. diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1872,3 +1872,46 @@ def isatty(fd): return fd.isatty() except AttributeError: return False + +timecount = unitcountfn( + (1, 1e3, _('%.0f s')), + (100, 1, _('%.1f s')), + (10, 1, _('%.2f s')), + (1, 1, _('%.3f s')), + (100, 0.001, _('%.1f ms')), + (10, 0.001, _('%.2f ms')), + (1, 0.001, _('%.3f ms')), + (100, 0.000001, _('%.1f us')), + (10, 0.000001, _('%.2f us')), + (1, 0.000001, _('%.3f us')), + (100, 0.000000001, _('%.1f ns')), + (10, 0.000000001, _('%.2f ns')), + (1, 0.000000001, _('%.3f ns')), + ) + +_timenesting = [0] + +def timed(func): + '''Report the execution time of a function call to stderr. + + During development, use as a decorator when you need to measure + the cost of a function, e.g. as follows: + + @util.timed + def foo(a, b, c): + pass + ''' + + def wrapper(*args, **kwargs): + start = time.time() + indent = 2 + _timenesting[0] += indent + try: + return func(*args, **kwargs) + finally: + elapsed = time.time() - start + _timenesting[0] -= indent + sys.stderr.write('%s%s: %s\n' % + (' ' * _timenesting[0], func.__name__, + timecount(elapsed))) + return wrapper