From f1557d47fbf0dddfecc5a08846464868323f7e54 Mon Sep 17 00:00:00 2001 From: David Peter Date: Sat, 5 Mar 2022 12:03:29 +0100 Subject: [PATCH] Add plot_progression.py --- CHANGELOG.md | 2 ++ scripts/plot_progression.py | 62 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100755 scripts/plot_progression.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 1af3b8a..0c084a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and #487 (@cipriancraciun and @sharkdp) - Added `--setup` (`s`) option that can be used to run `make all` or similar. It runs once per set of tests, like `--cleanup` (`c`). +- Added new `plot_progression.py` script to debug background interference + effects. ## Changes diff --git a/scripts/plot_progression.py b/scripts/plot_progression.py new file mode 100755 index 0000000..2545a57 --- /dev/null +++ b/scripts/plot_progression.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +"""This program shows `hyperfine` benchmark results in a sequential way +in order to debug possible background interference, caching effects, +thermal throttling and similar effects. +""" + +import argparse +import json +import matplotlib.pyplot as plt +import numpy as np + + +def moving_average(times, num_runs): + times_padded = np.pad( + times, (num_runs // 2, num_runs - 1 - num_runs // 2), mode="edge" + ) + kernel = np.ones(num_runs) / num_runs + return np.convolve(times_padded, kernel, mode="valid") + + +parser = argparse.ArgumentParser(description=__doc__) +parser.add_argument("file", help="JSON file with benchmark results") +parser.add_argument("--title", help="Plot Title") +parser.add_argument("-o", "--output", help="Save image to the given filename.") +parser.add_argument( + "-w", + "--moving-average-width", + type=int, + metavar="num_runs", + help="Width of the moving-average window (default: N/5)", +) + +args = parser.parse_args() + +with open(args.file) as f: + results = json.load(f)["results"] + +label = results[0]["command"] +times = results[0]["times"] +num = len(times) +nums = range(num) + +plt.scatter(x=nums, y=times, marker=".", color="orange") +plt.ylim([0, None]) +plt.xlim([-1, num]) + +moving_average_width = ( + num // 5 if args.moving_average_width is None else args.moving_average_width +) + +moving_average = moving_average(times, moving_average_width) +plt.plot(nums, moving_average, "-", color="blue") + +if args.title: + plt.title(args.title) +plt.legend(labels=[label], loc="best", fontsize="medium") +plt.ylabel("Time [s]") +if args.output: + plt.savefig(args.output) +else: + plt.show()