From 9f60cb4d93257fdd36703a7e7a2e1b641cd456ec Mon Sep 17 00:00:00 2001 From: Piotr Balcer Date: Fri, 8 Nov 2024 12:45:01 +0100 Subject: [PATCH] [benchmarks] HTML output improvements This patch is mostly a few minor changes to the bar charts to make them more legible. --- scripts/benchmarks/main.py | 6 ++-- scripts/benchmarks/output_html.py | 60 +++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/scripts/benchmarks/main.py b/scripts/benchmarks/main.py index 0756554e77..a31268a240 100755 --- a/scripts/benchmarks/main.py +++ b/scripts/benchmarks/main.py @@ -114,7 +114,6 @@ def main(directory, additional_env_vars, save_name, compare_names, filter): history.load(1000) for name in compare_names: - print(f"compare name: {name}") compare_result = history.get_compare(name) if compare_result: chart_data[name] = compare_result.results @@ -125,6 +124,8 @@ def main(directory, additional_env_vars, save_name, compare_names, filter): with open('benchmark_results.md', 'w') as file: file.write(markdown_content) + print(f"Markdown with benchmark results has been written to {os.getcwd()}/benchmark_results.md") + saved_name = save_name if save_name is not None else this_name # It's important we don't save the current results into history before @@ -132,7 +133,6 @@ def main(directory, additional_env_vars, save_name, compare_names, filter): # Otherwise we might be comparing the results to themselves. if not options.dry_run: history.save(saved_name, results, save_name is not None) - print(f"Markdown with benchmark results has been written to {os.getcwd()}/benchmark_results.md") compare_names.append(saved_name) if options.output_html: @@ -141,7 +141,7 @@ def main(directory, additional_env_vars, save_name, compare_names, filter): with open('benchmark_results.html', 'w') as file: file.write(html_content) - print(f"HTML with benchmark results has been written to {os.getcwd()}/benchmark_results.html") + print(f"HTML with benchmark results has been written to {os.getcwd()}/benchmark_results.html") def validate_and_parse_env_args(env_args): env_vars = {} diff --git a/scripts/benchmarks/output_html.py b/scripts/benchmarks/output_html.py index 8249bc75c9..4a04252797 100644 --- a/scripts/benchmarks/output_html.py +++ b/scripts/benchmarks/output_html.py @@ -3,6 +3,7 @@ # See LICENSE.TXT # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import re import matplotlib.pyplot as plt import mpld3 from collections import defaultdict @@ -67,12 +68,22 @@ def prepare_normalized_data(latest_results: dict[str, LatestResults], return normalized_data def format_benchmark_label(label: str) -> list[str]: - words = label.split() - if len(words) <= 2: - return [label] + words = re.split(' |_', label) + lines = [] + current_line = [] - mid = len(words) // 2 - return [' '.join(words[:mid]), ' '.join(words[mid:])] + # max line length 30 + for word in words: + if len(' '.join(current_line + [word])) > 30: + lines.append(' '.join(current_line)) + current_line = [word] + else: + current_line.append(word) + + if current_line: + lines.append(' '.join(current_line)) + + return lines def create_bar_plot(ax: plt.Axes, normalized_data: list[list[float]], @@ -109,9 +120,8 @@ def create_bar_plot(ax: plt.Axes, tooltip_labels = [ f"Run: {run_name}\n" - f"Benchmark: {benchmark_label}\n" f"Value: {current_value:.2f} {unit}\n" - f"Baseline ({baseline_name}): {baseline_value:.2f} {unit}\n" + f"Normalized to ({baseline_name}): {baseline_value:.2f} {unit}\n" f"Normalized: {value:.1f}%" ] tooltip = mpld3.plugins.LineHTMLTooltip(rect, tooltip_labels, css='.mpld3-tooltip{background:white;padding:8px;border:1px solid #ddd;border-radius:4px;font-family:monospace;white-space:pre;}') @@ -141,6 +151,37 @@ def add_chart_elements(ax: plt.Axes, ax.grid(True, axis='y', alpha=0.2) ax.legend(bbox_to_anchor=(1, 1), loc='upper left') +def split_large_groups(benchmark_groups): + miscellaneous = [] + new_groups = defaultdict(list) + + split_happened = False + for group, labels in benchmark_groups.items(): + if len(labels) == 1: + miscellaneous.extend(labels) + elif len(labels) > 5: + split_happened = True + mid = len(labels) // 2 + new_groups[group] = labels[:mid] + new_groups[group + '_'] = labels[mid:] + else: + new_groups[group] = labels + + if miscellaneous: + new_groups['Miscellaneous'] = miscellaneous + + if split_happened: + return split_large_groups(new_groups) + else: + return new_groups + +def group_benchmark_labels(benchmark_labels): + benchmark_groups = defaultdict(list) + for label in benchmark_labels: + group = re.match(r'^[^_\s]+', label)[0] + benchmark_groups[group].append(label) + return split_large_groups(benchmark_groups) + def create_normalized_bar_chart(benchmarks: list[BenchmarkSeries], baseline_name: str) -> list[str]: latest_results = get_latest_results(benchmarks) @@ -154,10 +195,7 @@ def create_normalized_bar_chart(benchmarks: list[BenchmarkSeries], baseline_name benchmark_labels = [b.label for b in benchmarks] - benchmark_groups = defaultdict(list) - for label in benchmark_labels: - group_name = label.split()[0] - benchmark_groups[group_name].append(label) + benchmark_groups = group_benchmark_labels(benchmark_labels) html_charts = []