Here is an update to Vadim Shender's clever code with tabular output:
import collections import time from functools import wraps PROF_DATA = {}collections.defaultdict(list) def profile(fn): @wraps(fn) def with_profiling(*args, **kwargs): start_time = time.time() ret = fn(*args, **kwargs) elapsed_time = time.time() - start_time if fn.__name__ not in PROF_DATA: PROF_DATA[fn.__name__] = [] PROF_DATA[fn.__name__].append(elapsed_time) return ret return with_profiling Metrics = collections.namedtuple("Metrics", "sum_time num_calls min_time max_time avg_time fname") def print_profile_data(): results = [] for fname, elapsed_times in PROF_DATA.items(): num_calls = len(elapsed_times) min_time = min(elapsed_times) max_time = max(elapsed_times) sum_time = sum(elapsed_times) avg_time = sum_time / num_calls metrics = Metrics(sum_time, num_calls, min_time, max_time, avg_time, fname) results.append(metrics) total_time = sum([m.sum_time for m in results]) print("\t".join(["Percent", "Sum", "Calls", "Min", "Max", "Mean", "Function"])) for m in sorted(results, reverse=True): print("%.1f\t%.3f\t%d\t%.3f\t%.3f\t%.3f\t%s" % (100 * m.sum_time / total_time, m.sum_time, m.num_calls, m.min_time, m.max_time, m.avg_time, m.fname)) print("%.3f Total Time" % total_time)