mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 18:15:28 +03:00
new diagrams in benchmarks
This commit is contained in:
@@ -2,8 +2,9 @@ __all__ = ["DiagramGenerator"]
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
import cairosvg
|
||||
import pygal
|
||||
from pygal.style import Style
|
||||
|
||||
from ..benchmarks.core.models import BenchmarkGroupResult
|
||||
|
||||
@@ -12,8 +13,26 @@ class DiagramGenerator:
|
||||
def __init__(self, output_dir: Path | str) -> None:
|
||||
self.output_dir: Path = Path(output_dir) if isinstance(output_dir, str) else output_dir
|
||||
|
||||
matplotlib.use("Agg")
|
||||
plt.style.use("seaborn-v0_8-whitegrid")
|
||||
self._style = Style(
|
||||
background="white",
|
||||
plot_background="white",
|
||||
foreground="#2c3e50",
|
||||
foreground_strong="#000000",
|
||||
foreground_subtle="#7f8c8d",
|
||||
opacity=".9",
|
||||
opacity_hover=".95",
|
||||
transition="150ms ease-in",
|
||||
colors=("#2ecc71", "#3498db", "#e74c3c"),
|
||||
title_font_size=40,
|
||||
legend_font_size=34,
|
||||
label_font_size=32, #
|
||||
major_label_font_size=32,
|
||||
value_font_size=28,
|
||||
value_label_font_size=28,
|
||||
tooltip_font_size=24,
|
||||
no_data_font_size=28,
|
||||
font_family="Consolas, 'Courier New', monospace",
|
||||
)
|
||||
|
||||
def generate_comparison_diagram(self, benchmark_group: BenchmarkGroupResult) -> Path:
|
||||
results = benchmark_group.benchmark_results
|
||||
@@ -31,132 +50,44 @@ class DiagramGenerator:
|
||||
)
|
||||
y_limit = max_value / 0.85 if max_value > 0 else 1.0
|
||||
|
||||
items_count = len(descriptions)
|
||||
x_positions: list[int] = list(range(items_count))
|
||||
|
||||
bar_width = 0.25
|
||||
|
||||
x_std_dev = [x - bar_width for x in x_positions]
|
||||
x_avg = [x for x in x_positions]
|
||||
x_median = [x + bar_width for x in x_positions]
|
||||
|
||||
fig, ax = plt.subplots(figsize=(16, 8))
|
||||
fig.patch.set_facecolor("white")
|
||||
|
||||
bars_std = ax.bar(
|
||||
x_std_dev,
|
||||
std_devs,
|
||||
bar_width,
|
||||
label="Std Deviation",
|
||||
color="#2ecc71",
|
||||
alpha=0.9,
|
||||
edgecolor="#27ae60",
|
||||
linewidth=1.5,
|
||||
)
|
||||
bars_avg = ax.bar(
|
||||
x_avg,
|
||||
avg_times,
|
||||
bar_width,
|
||||
label="Average Time",
|
||||
color="#3498db",
|
||||
alpha=0.9,
|
||||
edgecolor="#2980b9",
|
||||
linewidth=1.5,
|
||||
)
|
||||
bars_median = ax.bar(
|
||||
x_median,
|
||||
median_times,
|
||||
bar_width,
|
||||
label="Median Time",
|
||||
color="#e74c3c",
|
||||
alpha=0.9,
|
||||
edgecolor="#c0392b",
|
||||
linewidth=1.5,
|
||||
)
|
||||
|
||||
for bar_group in [bars_std, bars_avg, bars_median]:
|
||||
for bar in bar_group:
|
||||
height = bar.get_height()
|
||||
ax.text(
|
||||
bar.get_x() + bar.get_width() / 2.0,
|
||||
height,
|
||||
f"{height:.3f}",
|
||||
ha="center",
|
||||
va="bottom",
|
||||
fontsize=9,
|
||||
fontweight="bold",
|
||||
)
|
||||
|
||||
ax.set_ylabel("Time (ms)", fontsize=14, fontweight="bold", labelpad=10)
|
||||
|
||||
title_text = f"{benchmark_group.type_.replace('_', ' ').title()}"
|
||||
metadata_text = f"Iterations: {benchmark_group.iterations} | GC: {'Disabled' if benchmark_group.is_gc_disabled else 'Enabled'}"
|
||||
|
||||
ax.text(
|
||||
0.5,
|
||||
1.08,
|
||||
title_text,
|
||||
transform=ax.transAxes,
|
||||
fontsize=18,
|
||||
fontweight="bold",
|
||||
ha="center",
|
||||
color="#2c3e50",
|
||||
metadata_text = (
|
||||
f"Iterations: {benchmark_group.iterations} | GC: "
|
||||
f"{'Disabled' if benchmark_group.is_gc_disabled else 'Enabled'}"
|
||||
)
|
||||
ax.text(
|
||||
0.5,
|
||||
1.03,
|
||||
metadata_text,
|
||||
transform=ax.transAxes,
|
||||
fontsize=12,
|
||||
ha="center",
|
||||
color="#7f8c8d",
|
||||
style="italic",
|
||||
)
|
||||
|
||||
ax.set_xticks(x_positions)
|
||||
ax.set_xticklabels([])
|
||||
|
||||
for i, (pos, desc) in enumerate(zip(x_positions, descriptions)):
|
||||
text_x_pos = pos - bar_width - (bar_width / 2)
|
||||
ax.text(
|
||||
text_x_pos,
|
||||
y_limit * 0.02,
|
||||
desc,
|
||||
rotation=90,
|
||||
va="bottom",
|
||||
ha="right",
|
||||
fontsize=10,
|
||||
color="#2c3e50",
|
||||
)
|
||||
|
||||
ax.set_ylim(0, y_limit)
|
||||
|
||||
legend = ax.legend(
|
||||
loc="upper left",
|
||||
fontsize=12,
|
||||
framealpha=0.95,
|
||||
edgecolor="#34495e",
|
||||
fancybox=True,
|
||||
shadow=True,
|
||||
)
|
||||
legend.get_frame().set_facecolor("#ecf0f1")
|
||||
|
||||
ax.grid(axis="y", alpha=0.4, linestyle="--", linewidth=0.8)
|
||||
ax.set_axisbelow(True)
|
||||
|
||||
ax.spines["top"].set_visible(False)
|
||||
ax.spines["right"].set_visible(False)
|
||||
ax.spines["left"].set_color("#7f8c8d")
|
||||
ax.spines["bottom"].set_color("#7f8c8d")
|
||||
|
||||
plt.tight_layout()
|
||||
|
||||
filename = f"{benchmark_group.type_}_comparison.png"
|
||||
output_path = self.output_dir / filename
|
||||
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
plt.savefig(output_path, dpi=200, bbox_inches="tight", facecolor="white")
|
||||
plt.close(fig)
|
||||
dynamic_height = 600 + (len(descriptions) * 150)
|
||||
|
||||
chart = pygal.HorizontalBar(
|
||||
style=self._style,
|
||||
width=3100,
|
||||
height=dynamic_height,
|
||||
explicit_size=True,
|
||||
show_legend=True,
|
||||
legend_at_bottom=True,
|
||||
print_values=True,
|
||||
print_values_position="top",
|
||||
legend_at_bottom_columns=3,
|
||||
range=(0, y_limit),
|
||||
zero=0,
|
||||
)
|
||||
|
||||
chart.title = f"{title_text}\n{metadata_text}"
|
||||
chart.x_title = "Time (ms)"
|
||||
chart.no_data_text = "No data"
|
||||
chart.value_formatter = lambda x: f"{x:.3f}"
|
||||
|
||||
chart.x_labels = descriptions
|
||||
|
||||
chart.add("Std Deviation", std_devs)
|
||||
chart.add("Average Time", avg_times)
|
||||
chart.add("Median Time", median_times)
|
||||
|
||||
svg_bytes = chart.render()
|
||||
cairosvg.svg2png(bytestring=svg_bytes, write_to=str(output_path))
|
||||
|
||||
return output_path
|
||||
|
||||
Reference in New Issue
Block a user