# HG changeset patch # User Augie Fackler # Date 1429218753 14400 # Node ID 670c1df688fdb854a5761b70290b410e2cbfc0f6 # Parent 80c5b2666a96709650ae39c482adc147a43dbf98 dispatch: add support for python-flamegraph[0] profiling This gives us nicer svg flame graphs for output, which can make understanding some types of performance problems significantly easier. 0: https://github.com/evanhempel/python-flamegraph/ diff -r 80c5b2666a96 -r 670c1df688fd mercurial/dispatch.py --- a/mercurial/dispatch.py Tue Apr 28 16:44:37 2015 -0400 +++ b/mercurial/dispatch.py Thu Apr 16 17:12:33 2015 -0400 @@ -921,6 +921,30 @@ stats.sort(field) stats.pprint(limit=limit, file=fp, climit=climit) +def flameprofile(ui, func, fp): + try: + from flamegraph import flamegraph + except ImportError: + raise util.Abort(_( + 'flamegraph not available - install from ' + 'https://github.com/evanhempel/python-flamegraph')) + freq = ui.configint('profiling', 'freq', default=1000) + filter_ = None + collapse_recursion = True + thread = flamegraph.ProfileThread(fp, 1.0 / freq, + filter_, collapse_recursion) + start_time = time.clock() + try: + thread.start() + func() + finally: + thread.stop() + thread.join() + print 'Collected %d stack frames (%d unique) in %2.2f seconds.' % ( + time.clock() - start_time, thread.num_frames(), + thread.num_frames(unique=True)) + + def statprofile(ui, func, fp): try: import statprof @@ -952,7 +976,7 @@ profiler = os.getenv('HGPROF') if profiler is None: profiler = ui.config('profiling', 'type', default='ls') - if profiler not in ('ls', 'stat'): + if profiler not in ('ls', 'stat', 'flame'): ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler) profiler = 'ls' @@ -967,6 +991,8 @@ try: if profiler == 'ls': return lsprofile(ui, checkargs, fp) + elif profiler == 'flame': + return flameprofile(ui, checkargs, fp) else: return statprofile(ui, checkargs, fp) finally: