Mercurial > hg
diff contrib/perf-utils/perf-revlog-write-plot.py @ 40958:abd7b75e80bc
contrib: provide a small script that draw performance plot
We have been using this script to look into the result of various runs of the
`hg perfrevlogwrite` command. It seems useful enough to be shared more widely.
author | Paul Morelle <paul.morelle@octobus.net> |
---|---|
date | Fri, 14 Dec 2018 18:15:19 +0100 |
parents | |
children | c3e5ce3a9483 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/perf-utils/perf-revlog-write-plot.py Fri Dec 14 18:15:19 2018 +0100 @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# +# Copyright 2018 Paul Morelle <Paul.Morelle@octobus.net> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. +# +# This script use the output of `hg perfrevlogwrite -T json --details` to draw +# various plot related to write performance in a revlog +# +# usage: perf-revlog-write-plot.py details.json +from __future__ import absolute_import, print_function +import json +import re + +import numpy as np +import scipy.signal + +from matplotlib import ( + pyplot as plt, + ticker as mticker, +) + + +def plot(data): + items = {} + re_title = re.compile(r'^revisions #\d+ of \d+, rev (\d+)$') + for item in data: + m = re_title.match(item['title']) + if m is None: + continue + + rev = int(m.group(1)) + items[rev] = item + + min_rev = min(items.keys()) + max_rev = max(items.keys()) + ary = np.empty((2, max_rev - min_rev + 1)) + for rev, item in items.items(): + ary[0][rev - min_rev] = rev + ary[1][rev - min_rev] = item['wall'] + + fig = plt.figure() + comb_plt = fig.add_subplot(211) + other_plt = fig.add_subplot(212) + + comb_plt.plot(ary[0], + np.cumsum(ary[1]), + color='red', + linewidth=1, + label='comb') + + plots = [] + p = other_plt.plot(ary[0], + ary[1], + color='red', + linewidth=1, + label='wall') + plots.append(p) + + colors = { + 10: ('green', 'xkcd:grass green'), + 100: ('blue', 'xkcd:bright blue'), + 1000: ('purple', 'xkcd:dark pink'), + } + for n, color in colors.items(): + avg_n = np.convolve(ary[1], np.full(n, 1. / n), 'valid') + p = other_plt.plot(ary[0][n - 1:], + avg_n, + color=color[0], + linewidth=1, + label='avg time last %d' % n) + plots.append(p) + + med_n = scipy.signal.medfilt(ary[1], n + 1) + p = other_plt.plot(ary[0], + med_n, + color=color[1], + linewidth=1, + label='median time last %d' % n) + plots.append(p) + + formatter = mticker.ScalarFormatter() + formatter.set_scientific(False) + formatter.set_useOffset(False) + + comb_plt.grid() + comb_plt.xaxis.set_major_formatter(formatter) + comb_plt.legend() + + other_plt.grid() + other_plt.xaxis.set_major_formatter(formatter) + leg = other_plt.legend() + leg2plot = {} + for legline, plot in zip(leg.get_lines(), plots): + legline.set_picker(5) + leg2plot[legline] = plot + + def onpick(event): + legline = event.artist + plot = leg2plot[legline] + visible = not plot[0].get_visible() + for l in plot: + l.set_visible(visible) + + if visible: + legline.set_alpha(1.0) + else: + legline.set_alpha(0.2) + fig.canvas.draw() + fig.canvas.mpl_connect('pick_event', onpick) + + plt.show() + + +if __name__ == '__main__': + import sys + + if len(sys.argv) > 1: + print('reading from %r' % sys.argv[1]) + with open(sys.argv[1], 'r') as fp: + plot(json.load(fp)) + else: + print('reading from stdin') + plot(json.load(sys.stdin))