plot_progression.py (1955B)
1 #!/usr/bin/env python 2 3 """This program shows `hyperfine` benchmark results in a sequential way 4 in order to debug possible background interference, caching effects, 5 thermal throttling and similar effects. 6 """ 7 8 import argparse 9 import json 10 import matplotlib.pyplot as plt 11 import numpy as np 12 13 14 def moving_average(times, num_runs): 15 times_padded = np.pad( 16 times, (num_runs // 2, num_runs - 1 - num_runs // 2), mode="edge" 17 ) 18 kernel = np.ones(num_runs) / num_runs 19 return np.convolve(times_padded, kernel, mode="valid") 20 21 22 parser = argparse.ArgumentParser(description=__doc__) 23 parser.add_argument("file", help="JSON file with benchmark results") 24 parser.add_argument("--title", help="Plot Title") 25 parser.add_argument("-o", "--output", help="Save image to the given filename.") 26 parser.add_argument( 27 "-w", 28 "--moving-average-width", 29 type=int, 30 metavar="num_runs", 31 help="Width of the moving-average window (default: N/5)", 32 ) 33 parser.add_argument( 34 "--no-moving-average", 35 action="store_true", 36 help="Do not show moving average curve", 37 ) 38 39 40 args = parser.parse_args() 41 42 with open(args.file) as f: 43 results = json.load(f)["results"] 44 45 for result in results: 46 label = result["command"] 47 times = result["times"] 48 num = len(times) 49 nums = range(num) 50 51 plt.scatter(x=nums, y=times, marker=".") 52 plt.ylim([0, None]) 53 plt.xlim([-1, num]) 54 55 if not args.no_moving_average: 56 moving_average_width = ( 57 num // 5 if args.moving_average_width is None else args.moving_average_width 58 ) 59 60 average = moving_average(times, moving_average_width) 61 plt.plot(nums, average, "-") 62 63 if args.title: 64 plt.title(args.title) 65 66 legend = [] 67 for result in results: 68 legend.append(result["command"]) 69 if not args.no_moving_average: 70 legend.append("moving average") 71 plt.legend(legend) 72 73 plt.ylabel("Time [s]") 74 75 if args.output: 76 plt.savefig(args.output) 77 else: 78 plt.show()