From e000ada0f3715db2e70074063c2dcdc34381faec Mon Sep 17 00:00:00 2001 From: Andrija Kolic Date: Thu, 29 Jan 2026 10:09:24 +0100 Subject: [PATCH 1/2] Add the benchmark files as-is from the issue description. --- .../python/matplotlib/3d_surface_wireframe.py | 79 ++++++++++++ .../python/matplotlib/OWNERS.toml | 6 + .../matplotlib/categorical_bar_and_box.py | 117 ++++++++++++++++++ .../matplotlib/distributions_hist_2d.py | 73 +++++++++++ .../python/matplotlib/polar_quiver_stream.py | 111 +++++++++++++++++ .../run_all_matplotlib_demos_inproc.py | 41 ++++++ .../python/matplotlib/simple_line_plot.py | 45 +++++++ .../python/matplotlib/subplots_and_styles.py | 82 ++++++++++++ 8 files changed, 554 insertions(+) create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/OWNERS.toml create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py new file mode 100644 index 0000000000..37702a6d8e --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +""" +3D plotting example: surface, wireframe, and contour projections. +Saves to PDF. + +Run: + python tst/3d_surface_wireframe.py +""" + +from pathlib import Path + +# Use a non-interactive backend to work in headless environments +import matplotlib +matplotlib.use("Agg") + +import matplotlib.pyplot as plt +import numpy as np +from mpl_toolkits.mplot3d import Axes3D # noqa: F401 # needed for 3D projection + + +def main() -> None: + out_path = Path(__file__).parent / "surface_3d.pdf" + + # Domain and function + x = np.linspace(-4, 4, 200) + y = np.linspace(-4, 4, 200) + X, Y = np.meshgrid(x, y) + + R = np.sqrt(X**2 + Y**2) + 1e-12 + Z = np.sin(R) / R + 0.15 * np.cos(3*X) * np.sin(3*Y) / (1 + 0.5 * (X**2 + Y**2)) + + fig = plt.figure(figsize=(7.5, 5.8), dpi=150) + ax = fig.add_subplot(111, projection="3d") + + # Surface with colormap + surf = ax.plot_surface(X, Y, Z, cmap="viridis", linewidth=0, antialiased=True, alpha=0.95) + + # Wireframe overlay (sparser grid to avoid clutter) + step = 10 + ax.plot_wireframe(X[::step, ::step], Y[::step, ::step], Z[::step, ::step], + rstride=1, cstride=1, color="k", linewidth=0.3, alpha=0.5) + + # Contour projections on Z, X, and Y planes + z_offset = Z.min() - 0.4 + ax.contour(X, Y, Z, zdir="z", offset=z_offset, cmap="viridis", levels=18, linewidths=0.8) + + x_offset = x.min() - 0.6 + ax.contour(X, Y, Z, zdir="x", offset=x_offset, cmap="magma", levels=14, linewidths=0.7) + + y_offset = y.max() + 0.6 + ax.contour(X, Y, Z, zdir="y", offset=y_offset, cmap="plasma", levels=14, linewidths=0.7) + + # Axes labels and limits + ax.set_xlabel("X") + ax.set_ylabel("Y") + ax.set_zlabel("Z") + + ax.set_xlim(x_offset, x.max()) + ax.set_ylim(y.min(), y_offset) + ax.set_zlim(z_offset, Z.max()) + + # Colorbar + cb = fig.colorbar(surf, ax=ax, shrink=0.6, aspect=12, pad=0.08) + cb.set_label("Z value") + + # View angle + ax.view_init(elev=25, azim=-55) + + ax.set_title("3D Surface + Wireframe + Contour Projections") + fig.tight_layout() + + fig.savefig(out_path, format="pdf") + plt.close(fig) + + print(f"Wrote PDF: {out_path.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/OWNERS.toml b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/OWNERS.toml new file mode 100644 index 0000000000..34cb11f338 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/OWNERS.toml @@ -0,0 +1,6 @@ +[[rule]] +files = "*" +any = [ + "francois.farquet@oracle.com", + "andrija.kolic@oracle.com", +] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py new file mode 100644 index 0000000000..f10116bec8 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +""" +Categorical plots: grouped bar chart with error bars and a boxplot. +Saves a multi-page PDF using PdfPages. + +Run: + python tst/categorical_bar_and_box.py +""" + +from pathlib import Path + +# Use a non-interactive backend to work in headless environments +import matplotlib +matplotlib.use("Agg") + +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.backends.backend_pdf import PdfPages + + +def _colorize_boxplot(bp, facecolor="#1f77b4", edgecolor="black", alpha=0.6): + for box in bp["boxes"]: + box.set(facecolor=facecolor, edgecolor=edgecolor, alpha=alpha) + for median in bp["medians"]: + median.set(color="black", linewidth=1.2) + for whisker in bp["whiskers"]: + whisker.set(color=edgecolor, linewidth=1.0) + for cap in bp["caps"]: + cap.set(color=edgecolor, linewidth=1.0) + for flier in bp["fliers"]: + flier.set(marker="o", markersize=3, markerfacecolor="white", markeredgecolor=edgecolor, alpha=0.7) + + +def main() -> None: + out_path = Path(__file__).parent / "categorical_plots.pdf" + + rng = np.random.default_rng(2024) + categories = ["A", "B", "C", "D"] + n = len(categories) + + with PdfPages(out_path) as pdf: + # Page 1: Grouped bar chart with error bars + x = np.arange(n) + bar_w = 0.35 + + means1 = rng.normal(3.0, 0.4, n) + errs1 = rng.uniform(0.1, 0.4, n) + + means2 = rng.normal(2.2, 0.5, n) + errs2 = rng.uniform(0.1, 0.4, n) + + fig1, ax1 = plt.subplots(figsize=(7, 4), dpi=150) + b1 = ax1.bar(x - bar_w / 2, means1, yerr=errs1, width=bar_w, capsize=3, + label="Series 1", color="#1f77b4", edgecolor="black", alpha=0.85) + b2 = ax1.bar(x + bar_w / 2, means2, yerr=errs2, width=bar_w, capsize=3, + label="Series 2", color="#ff7f0e", edgecolor="black", alpha=0.85) + + ax1.set_xticks(x, categories) + ax1.set_ylabel("Value") + ax1.set_title("Grouped Bar Chart with Error Bars") + ax1.grid(axis="y", linestyle="--", alpha=0.35) + ax1.legend(loc="best") + + # Annotate bars with heights + for bars in (b1, b2): + for rect in bars: + h = rect.get_height() + ax1.text(rect.get_x() + rect.get_width() / 2.0, h + 0.05, + f"{h:.2f}", ha="center", va="bottom", fontsize=8, rotation=0) + + fig1.tight_layout() + pdf.savefig(fig1) + plt.close(fig1) + + # Page 2: Boxplot across categories + # Generate some synthetic distributions with varying mean/variance + mus = [2.8, 3.2, 2.5, 3.5] + sigmas = [0.50, 0.60, 0.45, 0.55] + data = [rng.normal(loc=m, scale=s, size=400) for m, s in zip(mus, sigmas)] + + fig2, ax2 = plt.subplots(figsize=(7, 4), dpi=150) + bp = ax2.boxplot( + data, + tick_labels=categories, + widths=0.6, + patch_artist=True, + showfliers=True, + whis=(5, 95), + ) + # Colorize boxes with a palette + palette = ["#1f77b4", "#ff7f0e", "#2ca02c", "#9467bd"] + for box, color in zip(bp["boxes"], palette): + box.set(facecolor=color, edgecolor="black", alpha=0.6) + + # Style the rest + for median in bp["medians"]: + median.set(color="black", linewidth=1.4) + for whisker in bp["whiskers"]: + whisker.set(color="black", linewidth=1.0) + for cap in bp["caps"]: + cap.set(color="black", linewidth=1.0) + for flier in bp["fliers"]: + flier.set(marker="o", markersize=3, markerfacecolor="white", markeredgecolor="black", alpha=0.7) + + ax2.set_title("Boxplot by Category") + ax2.set_ylabel("Distribution") + ax2.grid(axis="y", linestyle="--", alpha=0.35) + fig2.tight_layout() + + pdf.savefig(fig2) + plt.close(fig2) + + print(f"Wrote PDF: {out_path.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py new file mode 100644 index 0000000000..d2a0151ede --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +Distribution plots: 1D histogram, 2D histogram, and hexbin with colorbars. + +Run: + python tst/distributions_hist_2d.py +""" + +from pathlib import Path + +# Use a non-interactive backend to work in headless environments +import matplotlib +matplotlib.use("Agg") + +import matplotlib.pyplot as plt +import numpy as np + + +def main() -> None: + out_path = Path(__file__).parent / "distributions_2d.pdf" + + rng = np.random.default_rng(7) + n = 6000 + + # Create two correlated variables + x = rng.normal(0.0, 1.0, n) + y = 0.65 * x + rng.normal(0.0, 0.8, n) + + fig, axs = plt.subplots(1, 3, figsize=(12, 4), dpi=150) + + # 1) 1D histograms overlayed + ax = axs[0] + ax.hist(x, bins=40, alpha=0.8, label="x", color="#1f77b4", edgecolor="white") + ax.hist(y, bins=40, alpha=0.6, label="y", color="#ff7f0e", edgecolor="white") + ax.set_title("1D Histograms") + ax.set_xlabel("Value") + ax.set_ylabel("Frequency") + ax.grid(True, linestyle="--", alpha=0.3) + ax.legend(loc="best") + + # 2) 2D histogram via pcolormesh + ax = axs[1] + H, xedges, yedges = np.histogram2d(x, y, bins=60) + X, Y = np.meshgrid(xedges, yedges) + pcm = ax.pcolormesh(X, Y, H.T, cmap="viridis", shading="auto") + ax.set_title("2D Histogram") + ax.set_xlabel("x") + ax.set_ylabel("y") + cb = fig.colorbar(pcm, ax=ax) + cb.set_label("Count") + ax.grid(False) + + # 3) Hexbin with log color scale + ax = axs[2] + hb = ax.hexbin(x, y, gridsize=45, cmap="plasma", mincnt=1, bins="log") + ax.set_title("Hexbin (log density)") + ax.set_xlabel("x") + ax.set_ylabel("y") + cb = fig.colorbar(hb, ax=ax) + cb.set_label("log10(count)") + ax.grid(False) + + fig.suptitle("Distributions: 1D and 2D Density", fontsize=14) + fig.tight_layout(rect=[0, 0.03, 1, 0.95]) + + fig.savefig(out_path, format="pdf") + plt.close(fig) + + print(f"Wrote PDF: {out_path.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py new file mode 100644 index 0000000000..fe83cac5ae --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +""" +Vector and polar plots: polar plot, quiver, and streamplot on separate pages. +Saves a multi-page PDF using PdfPages. + +Run: + python tst/polar_quiver_stream.py +""" + +from pathlib import Path + +# Use a non-interactive backend to work in headless environments +import matplotlib +matplotlib.use("Agg") + +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.backends.backend_pdf import PdfPages + + +def page_polar(ax): + # Polar demo with multiple radii and an area fill + theta = np.linspace(0, 2*np.pi, 512) + r1 = 1.0 + 0.3*np.sin(5*theta) + r2 = 0.7 + 0.2*np.cos(3*theta + 0.5) + + ax.plot(theta, r1, color="#1f77b4", linewidth=2.0, label="r1(θ) = 1 + 0.3 sin(5θ)") + ax.plot(theta, r2, color="#ff7f0e", linewidth=2.0, linestyle="--", label="r2(θ) = 0.7 + 0.2 cos(3θ+0.5)") + ax.fill_between(theta, r2, color="#ff7f0e", alpha=0.25, step="mid") + ax.set_theta_zero_location("N") + ax.set_theta_direction(-1) + ax.set_title("Polar Plot", va="bottom") + ax.grid(True, alpha=0.4) + ax.legend(loc="upper right", bbox_to_anchor=(1.25, 1.15), frameon=False) + + +def page_quiver(ax): + # Quiver plot for a simple rotational vector field + n = 25 + x = np.linspace(-2.0, 2.0, n) + y = np.linspace(-2.0, 2.0, n) + X, Y = np.meshgrid(x, y) + + # Vector field: rotation around origin + U = -Y + V = X + speed = np.hypot(U, V) + + q = ax.quiver(X, Y, U, V, speed, cmap="viridis", pivot="mid", angles="xy", scale=35, width=0.006) + ax.set_aspect("equal", adjustable="box") + ax.set_title("Quiver: Rotational Field") + ax.set_xlabel("x") + ax.set_ylabel("y") + cb = ax.figure.colorbar(q, ax=ax, pad=0.01) + cb.set_label("|v|") + ax.grid(True, linestyle="--", alpha=0.3) + + +def page_streamplot(ax): + # Streamplot with linewidth and color mapped to speed + x = np.linspace(-3.0, 3.0, 200) + y = np.linspace(-3.0, 3.0, 200) + X, Y = np.meshgrid(x, y) + + # Double-vortex-like field + U = 1 - (X**2) + (Y**2) + V = -2*X*Y + speed = np.sqrt(U**2 + V**2) + + lw = 1.5 * speed / (speed.max() + 1e-12) + strm = ax.streamplot(X, Y, U, V, color=speed, linewidth=lw, cmap="plasma", density=1.4, arrowsize=1.2) + ax.set_aspect("equal", adjustable="box") + ax.set_title("Streamplot: Speed-coded") + ax.set_xlabel("x") + ax.set_ylabel("y") + cb = ax.figure.colorbar(strm.lines, ax=ax, pad=0.01) + cb.set_label("|v|") + ax.grid(True, linestyle="--", alpha=0.25) + + +def main() -> None: + out_path = Path(__file__).parent / "vector_and_polar.pdf" + + with PdfPages(out_path) as pdf: + # Page 1: Polar + fig1 = plt.figure(figsize=(6.2, 5.5), dpi=150) + ax1 = fig1.add_subplot(111, projection="polar") + page_polar(ax1) + fig1.tight_layout() + pdf.savefig(fig1) + plt.close(fig1) + + # Page 2: Quiver + fig2, ax2 = plt.subplots(figsize=(6.2, 5.0), dpi=150) + page_quiver(ax2) + fig2.tight_layout() + pdf.savefig(fig2) + plt.close(fig2) + + # Page 3: Streamplot + fig3, ax3 = plt.subplots(figsize=(6.6, 5.2), dpi=150) + page_streamplot(ax3) + fig3.tight_layout() + pdf.savefig(fig3) + plt.close(fig3) + + print(f"Wrote PDF: {out_path.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py new file mode 100644 index 0000000000..e5b9956355 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +""" +Run all matplotlib demo scripts in this directory in a single Python process. + +Usage: + python tst/run_all_matplotlib_demos_inproc.py +""" + +from pathlib import Path +import runpy +import time + +# Force a headless backend once for the entire process, before any pyplot import. +import matplotlib +matplotlib.use("Agg") +# Make subsequent matplotlib.use(...) calls inside the demo scripts a no-op. +matplotlib.use = lambda *args, **kwargs: None # type: ignore[assignment] + +BASE = Path(__file__).parent + +SCRIPTS = [ + "simple_line_plot.py", + "subplots_and_styles.py", + "categorical_bar_and_box.py", + "distributions_hist_2d.py", + "polar_quiver_stream.py", + "3d_surface_wireframe.py", +] +while True: + print(f"=== RUN iteration ===") + start1 = time.time() + for script in SCRIPTS: + print(f" === RUN {script} ===") + start = time.time() + runpy.run_path(str(BASE / script), run_name="__main__") + dur = time.time() - start + print(f" time: {dur}") + dur = time.time() - start1 + print(f"overall time: {dur}") + +print("All demo scripts executed in one process.") diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py new file mode 100644 index 0000000000..0a970c471a --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +""" +Simple line plot example that saves to PDF. + +Run: + python tst/simple_line_plot.py +""" + +import os +from pathlib import Path + +# Use a non-interactive backend to work in headless environments +import matplotlib +matplotlib.use("Agg") + +import matplotlib.pyplot as plt +import numpy as np + + +def main() -> None: + out_path = Path(__file__).parent / "simple_line_plot.pdf" + + # Reproducible data + rng = np.random.default_rng(42) + x = np.linspace(0.0, 10.0, 200) + y = np.sin(x) + 0.15 * rng.standard_normal(x.size) + + plt.figure(figsize=(6, 4), dpi=150) + plt.plot(x, np.sin(x), label="sin(x)", color="#1f77b4", linewidth=2.0) + plt.scatter(x[::8], y[::8], label="samples", color="#ff7f0e", s=15, alpha=0.85) + plt.title("Simple Line + Sampled Points") + plt.xlabel("x") + plt.ylabel("y") + plt.grid(True, linestyle="--", alpha=0.4) + plt.legend(loc="best") + plt.tight_layout() + + plt.savefig(out_path, format="pdf") + plt.close() + + print(f"Wrote PDF: {out_path.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py new file mode 100644 index 0000000000..f340df2475 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +""" +Subplots and style variations; saves a multi-panel PDF. + +Run: + python tst/subplots_and_styles.py +""" + +from pathlib import Path + +# Use a non-interactive backend to work in headless environments +import matplotlib +matplotlib.use("Agg") + +import matplotlib.pyplot as plt +import numpy as np + + +def main() -> None: + out_path = Path(__file__).parent / "subplots_and_styles.pdf" + + rng = np.random.default_rng(123) + x = np.linspace(0, 2*np.pi, 200) + y1 = np.sin(x) + y2 = np.cos(x) + y3 = np.sin(2*x) * np.exp(-0.3*x) + y4 = rng.normal(loc=0.0, scale=1.0, size=200) + + fig, axs = plt.subplots(2, 2, figsize=(8, 6), dpi=150) + + # 1) Basic line styles + ax = axs[0, 0] + ax.plot(x, y1, label="sin(x)", color="#1f77b4", linewidth=2.0) + ax.plot(x, y2, label="cos(x)", color="#ff7f0e", linestyle="--", linewidth=2.0) + ax.set_title("Line Styles") + ax.set_xlabel("x") + ax.set_ylabel("y") + ax.grid(True, linestyle=":", alpha=0.5) + ax.legend(loc="best") + + # 2) Markers and transparency + ax = axs[0, 1] + ax.plot(x, y3, color="#2ca02c", linewidth=1.5) + ax.scatter(x[::10], y3[::10], color="#d62728", s=20, alpha=0.8, label="samples") + ax.set_title("Markers and Decay") + ax.annotate("decay", xy=(2.0, y3[np.searchsorted(x, 2.0)]), xytext=(3.5, 0.8), + arrowprops=dict(arrowstyle="->", color="gray"), color="gray") + ax.grid(True, alpha=0.4) + ax.legend(loc="best") + + # 3) Simple bar chart + ax = axs[1, 0] + categories = ["A", "B", "C", "D", "E"] + values = np.abs(rng.normal(3.0, 1.0, size=len(categories))) + bars = ax.bar(categories, values, color="#9467bd", edgecolor="black", alpha=0.85) + for b in bars: + ax.text(b.get_x() + b.get_width()/2, b.get_height() + 0.05, + f"{b.get_height():.1f}", ha="center", va="bottom", fontsize=8) + ax.set_title("Bar Chart") + ax.set_ylabel("Value") + ax.set_ylim(0, max(values) * 1.2) + ax.grid(axis="y", linestyle="--", alpha=0.3) + + # 4) Histogram with style + ax = axs[1, 1] + ax.hist(y4, bins=20, color="#8c564b", edgecolor="white", alpha=0.9) + ax.set_title("Histogram") + ax.set_xlabel("Value") + ax.set_ylabel("Frequency") + ax.grid(True, linestyle="--", alpha=0.3) + + fig.suptitle("Subplots and Styles", fontsize=14) + fig.tight_layout(rect=[0, 0.03, 1, 0.95]) + + fig.savefig(out_path, format="pdf") + plt.close(fig) + + print(f"Wrote PDF: {out_path.resolve()}") + + +if __name__ == "__main__": + main() From 0a9d1addb9e52906a784946b41655bf79b594861 Mon Sep 17 00:00:00 2001 From: Andrija Kolic Date: Thu, 29 Jan 2026 14:56:00 +0100 Subject: [PATCH 2/2] Adjust the benchmark files to the PolyBench contract. --- .../python/matplotlib/3d_surface_wireframe.py | 78 +++++++++++++---- .../matplotlib/categorical_bar_and_box.py | 85 ++++++++++++++---- .../matplotlib/distributions_hist_2d.py | 77 ++++++++++++++--- .../python/matplotlib/polar_quiver_stream.py | 86 +++++++++++++++---- .../run_all_matplotlib_demos_inproc.py | 41 --------- .../python/matplotlib/simple_line_plot.py | 78 +++++++++++++---- .../python/matplotlib/subplots_and_styles.py | 77 ++++++++++++++--- mx.graalpython/OWNERS.toml | 6 ++ .../polybench-stable-run-config.json | 30 +++++++ mx.graalpython/suite.py | 3 + 10 files changed, 427 insertions(+), 134 deletions(-) delete mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py create mode 100644 mx.graalpython/OWNERS.toml diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py index 37702a6d8e..96ac2bdb65 100644 --- a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/3d_surface_wireframe.py @@ -1,24 +1,62 @@ #!/usr/bin/env python3 +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """ 3D plotting example: surface, wireframe, and contour projections. Saves to PDF. - -Run: - python tst/3d_surface_wireframe.py """ -from pathlib import Path - -# Use a non-interactive backend to work in headless environments -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import numpy as np -from mpl_toolkits.mplot3d import Axes3D # noqa: F401 # needed for 3D projection +def run(): + # Execute all imports inside the `run` method so they're measured + from pathlib import Path + # Use a non-interactive backend to work in headless environments + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + import numpy as np + # Ensure we have version info in the logs + print(f"Using matplotlib version '{matplotlib.__version__}'") + print(f"Using numpy version '{np.__version__}'") -def main() -> None: out_path = Path(__file__).parent / "surface_3d.pdf" # Domain and function @@ -72,8 +110,18 @@ def main() -> None: fig.savefig(out_path, format="pdf") plt.close(fig) - print(f"Wrote PDF: {out_path.resolve()}") + +def warmupIterations(): + return 0 + + +def iterations(): + return 1 -if __name__ == "__main__": - main() +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py index f10116bec8..6fa26ce37a 100644 --- a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/categorical_bar_and_box.py @@ -1,22 +1,48 @@ #!/usr/bin/env python3 +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """ Categorical plots: grouped bar chart with error bars and a boxplot. Saves a multi-page PDF using PdfPages. - -Run: - python tst/categorical_bar_and_box.py """ -from pathlib import Path - -# Use a non-interactive backend to work in headless environments -import matplotlib -matplotlib.use("Agg") - -import matplotlib.pyplot as plt -import numpy as np -from matplotlib.backends.backend_pdf import PdfPages - def _colorize_boxplot(bp, facecolor="#1f77b4", edgecolor="black", alpha=0.6): for box in bp["boxes"]: @@ -31,7 +57,20 @@ def _colorize_boxplot(bp, facecolor="#1f77b4", edgecolor="black", alpha=0.6): flier.set(marker="o", markersize=3, markerfacecolor="white", markeredgecolor=edgecolor, alpha=0.7) -def main() -> None: +def run(): + # Execute all imports inside the `run` method so they're measured + from pathlib import Path + # Use a non-interactive backend to work in headless environments + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + import numpy as np + from matplotlib.backends.backend_pdf import PdfPages + + # Ensure we have version info in the logs + print(f"Using matplotlib version '{matplotlib.__version__}'") + print(f"Using numpy version '{np.__version__}'") + out_path = Path(__file__).parent / "categorical_plots.pdf" rng = np.random.default_rng(2024) @@ -81,7 +120,7 @@ def main() -> None: fig2, ax2 = plt.subplots(figsize=(7, 4), dpi=150) bp = ax2.boxplot( data, - tick_labels=categories, + labels=categories, widths=0.6, patch_artist=True, showfliers=True, @@ -110,8 +149,18 @@ def main() -> None: pdf.savefig(fig2) plt.close(fig2) - print(f"Wrote PDF: {out_path.resolve()}") + +def warmupIterations(): + return 0 + + +def iterations(): + return 1 -if __name__ == "__main__": - main() +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py index d2a0151ede..092d2aa746 100644 --- a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/distributions_hist_2d.py @@ -1,22 +1,61 @@ #!/usr/bin/env python3 +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """ Distribution plots: 1D histogram, 2D histogram, and hexbin with colorbars. - -Run: - python tst/distributions_hist_2d.py """ -from pathlib import Path - -# Use a non-interactive backend to work in headless environments -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import numpy as np +def run(): + # Execute all imports inside the `run` method so they're measured + from pathlib import Path + # Use a non-interactive backend to work in headless environments + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + import numpy as np + # Ensure we have version info in the logs + print(f"Using matplotlib version '{matplotlib.__version__}'") + print(f"Using numpy version '{np.__version__}'") -def main() -> None: out_path = Path(__file__).parent / "distributions_2d.pdf" rng = np.random.default_rng(7) @@ -66,8 +105,18 @@ def main() -> None: fig.savefig(out_path, format="pdf") plt.close(fig) - print(f"Wrote PDF: {out_path.resolve()}") + +def warmupIterations(): + return 0 + + +def iterations(): + return 1 -if __name__ == "__main__": - main() +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py index fe83cac5ae..192d984f63 100644 --- a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/polar_quiver_stream.py @@ -1,25 +1,52 @@ #!/usr/bin/env python3 +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """ Vector and polar plots: polar plot, quiver, and streamplot on separate pages. Saves a multi-page PDF using PdfPages. - -Run: - python tst/polar_quiver_stream.py """ -from pathlib import Path - -# Use a non-interactive backend to work in headless environments -import matplotlib -matplotlib.use("Agg") - -import matplotlib.pyplot as plt -import numpy as np -from matplotlib.backends.backend_pdf import PdfPages - def page_polar(ax): # Polar demo with multiple radii and an area fill + import numpy as np theta = np.linspace(0, 2*np.pi, 512) r1 = 1.0 + 0.3*np.sin(5*theta) r2 = 0.7 + 0.2*np.cos(3*theta + 0.5) @@ -36,6 +63,7 @@ def page_polar(ax): def page_quiver(ax): # Quiver plot for a simple rotational vector field + import numpy as np n = 25 x = np.linspace(-2.0, 2.0, n) y = np.linspace(-2.0, 2.0, n) @@ -58,6 +86,7 @@ def page_quiver(ax): def page_streamplot(ax): # Streamplot with linewidth and color mapped to speed + import numpy as np x = np.linspace(-3.0, 3.0, 200) y = np.linspace(-3.0, 3.0, 200) X, Y = np.meshgrid(x, y) @@ -78,7 +107,20 @@ def page_streamplot(ax): ax.grid(True, linestyle="--", alpha=0.25) -def main() -> None: +def run(): + # Execute all imports inside the `run` method so they're measured + from pathlib import Path + # Use a non-interactive backend to work in headless environments + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + import numpy as np + from matplotlib.backends.backend_pdf import PdfPages + + # Ensure we have version info in the logs + print(f"Using matplotlib version '{matplotlib.__version__}'") + print(f"Using numpy version '{np.__version__}'") + out_path = Path(__file__).parent / "vector_and_polar.pdf" with PdfPages(out_path) as pdf: @@ -104,8 +146,18 @@ def main() -> None: pdf.savefig(fig3) plt.close(fig3) - print(f"Wrote PDF: {out_path.resolve()}") + +def warmupIterations(): + return 0 + + +def iterations(): + return 1 -if __name__ == "__main__": - main() +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py deleted file mode 100644 index e5b9956355..0000000000 --- a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/run_all_matplotlib_demos_inproc.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -""" -Run all matplotlib demo scripts in this directory in a single Python process. - -Usage: - python tst/run_all_matplotlib_demos_inproc.py -""" - -from pathlib import Path -import runpy -import time - -# Force a headless backend once for the entire process, before any pyplot import. -import matplotlib -matplotlib.use("Agg") -# Make subsequent matplotlib.use(...) calls inside the demo scripts a no-op. -matplotlib.use = lambda *args, **kwargs: None # type: ignore[assignment] - -BASE = Path(__file__).parent - -SCRIPTS = [ - "simple_line_plot.py", - "subplots_and_styles.py", - "categorical_bar_and_box.py", - "distributions_hist_2d.py", - "polar_quiver_stream.py", - "3d_surface_wireframe.py", -] -while True: - print(f"=== RUN iteration ===") - start1 = time.time() - for script in SCRIPTS: - print(f" === RUN {script} ===") - start = time.time() - runpy.run_path(str(BASE / script), run_name="__main__") - dur = time.time() - start - print(f" time: {dur}") - dur = time.time() - start1 - print(f"overall time: {dur}") - -print("All demo scripts executed in one process.") diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py index 0a970c471a..8333b80f53 100644 --- a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/simple_line_plot.py @@ -1,23 +1,61 @@ #!/usr/bin/env python3 +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """ Simple line plot example that saves to PDF. - -Run: - python tst/simple_line_plot.py """ -import os -from pathlib import Path - -# Use a non-interactive backend to work in headless environments -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import numpy as np +def run(): + # Execute all imports inside the `run` method so they're measured + from pathlib import Path + # Use a non-interactive backend to work in headless environments + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + import numpy as np + # Ensure we have version info in the logs + print(f"Using matplotlib version '{matplotlib.__version__}'") + print(f"Using numpy version '{np.__version__}'") -def main() -> None: out_path = Path(__file__).parent / "simple_line_plot.pdf" # Reproducible data @@ -38,8 +76,18 @@ def main() -> None: plt.savefig(out_path, format="pdf") plt.close() - print(f"Wrote PDF: {out_path.resolve()}") + +def warmupIterations(): + return 0 + + +def iterations(): + return 1 -if __name__ == "__main__": - main() +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py index f340df2475..011a2b612b 100644 --- a/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py +++ b/graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/subplots_and_styles.py @@ -1,22 +1,61 @@ #!/usr/bin/env python3 +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """ Subplots and style variations; saves a multi-panel PDF. - -Run: - python tst/subplots_and_styles.py """ -from pathlib import Path - -# Use a non-interactive backend to work in headless environments -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import numpy as np +def run(): + # Execute all imports inside the `run` method so they're measured + from pathlib import Path + # Use a non-interactive backend to work in headless environments + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + import numpy as np + # Ensure we have version info in the logs + print(f"Using matplotlib version '{matplotlib.__version__}'") + print(f"Using numpy version '{np.__version__}'") -def main() -> None: out_path = Path(__file__).parent / "subplots_and_styles.pdf" rng = np.random.default_rng(123) @@ -75,8 +114,18 @@ def main() -> None: fig.savefig(out_path, format="pdf") plt.close(fig) - print(f"Wrote PDF: {out_path.resolve()}") + +def warmupIterations(): + return 0 + + +def iterations(): + return 1 -if __name__ == "__main__": - main() +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/mx.graalpython/OWNERS.toml b/mx.graalpython/OWNERS.toml new file mode 100644 index 0000000000..9e9526a0fe --- /dev/null +++ b/mx.graalpython/OWNERS.toml @@ -0,0 +1,6 @@ +[[rule]] +files = "polybench-stable-run-config.json" +any = [ + "francois.farquet@oracle.com", + "andrija.kolic@oracle.com", +] diff --git a/mx.graalpython/polybench-stable-run-config.json b/mx.graalpython/polybench-stable-run-config.json index 3341e29995..f7a1ab9c5b 100644 --- a/mx.graalpython/polybench-stable-run-config.json +++ b/mx.graalpython/polybench-stable-run-config.json @@ -726,5 +726,35 @@ "policy": "outlier-elimination-all-builds", "forks": "1x1", "focus": "0.0-1.0" + }, + "warmup/matplotlib/3d_surface_wireframe.py": { + "policy": "outlier-elimination-all-builds", + "forks": "5x3", + "focus": "0.3-0.7" + }, + "warmup/matplotlib/categorical_bar_and_box.py": { + "policy": "outlier-elimination-all-builds", + "forks": "5x3", + "focus": "0.4-0.6" + }, + "warmup/matplotlib/distributions_hist_2d.py": { + "policy": "outlier-elimination-all-builds", + "forks": "3x5", + "focus": "0.4-0.9" + }, + "warmup/matplotlib/polar_quiver_stream.py": { + "policy": "outlier-elimination-all-builds", + "forks": "0x0", + "focus": "0.5-0.85" + }, + "warmup/matplotlib/simple_line_plot.py": { + "policy": "outlier-elimination-all-builds", + "forks": "4x3", + "focus": "0.0-0.4" + }, + "warmup/matplotlib/subplots_and_styles.py": { + "policy": "outlier-elimination-all-builds", + "forks": "5x5", + "focus": "0.3-0.7" } } diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index a67f5946f3..07d4f2b413 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -1652,6 +1652,9 @@ "file:benchmarks/warmup/*.py", "dependency:GRAALPYTHON_PYFLATE_BENCHMARK_RESOURCE", ], + "./warmup/matplotlib/": [ + "file:graalpython/com.oracle.graal.python.benchmarks/python/matplotlib/*.py", + ], }, },