{ "cells": [ { "cell_type": "markdown", "id": "07ee141c-4587-4f89-a70c-97094df947b1", "metadata": {}, "source": [ "# Benchmark visualizer\n", "\n", "This notebook compares everyone's code performance." ] }, { "cell_type": "code", "execution_count": null, "id": "bfb56e64-f4b1-4a99-8edf-4ae530ded1ed", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import matplotlib.ticker as mticker\n", "import pandas as pd\n", "import seaborn as sns\n", "\n", "import compare\n", "\n", "# TODO: Move some of this stuff into compare.py\n", "catppuccin_latte = {\n", " \"rosewater\": \"#dc8a78\",\n", " \"flamingo\": \"#dd7878\",\n", " \"pink\": \"#ea76cb\",\n", " \"mauve\": \"#8839ef\",\n", " \"red\": \"#d20f39\",\n", " \"maroon\": \"#e64553\",\n", " \"peach\": \"#fe640b\",\n", " \"yellow\": \"#df8e1d\",\n", " \"green\": \"#40a02b\",\n", " \"teal\": \"#179299\",\n", " \"sky\": \"#04a5e5\",\n", " \"sapphire\": \"#209fb5\",\n", " \"blue\": \"#1e66f5\",\n", " \"lavender\": \"#7287fd\",\n", "\n", " # UI base\n", " \"text\": \"#4c4f69\",\n", " \"surface\": \"#eff1f5\",\n", " \"overlay\": \"#e6e9ef\",\n", "}\n", "\n", "plt.rcParams.update({\n", " \"figure.facecolor\": \"white\",\n", " \"axes.facecolor\": \"white\",\n", " \"savefig.facecolor\": \"white\",\n", " \"text.color\": catppuccin_latte[\"text\"],\n", " \"axes.labelcolor\": catppuccin_latte[\"text\"],\n", " \"xtick.color\": catppuccin_latte[\"text\"],\n", " \"ytick.color\": catppuccin_latte[\"text\"],\n", " \"axes.edgecolor\": catppuccin_latte[\"text\"],\n", "})\n", "sns.set_style(\"whitegrid\", {\n", " \"axes.facecolor\": \"white\",\n", " \"grid.color\": catppuccin_latte[\"overlay\"],\n", "})\n", "\n", "PALETTE = {\n", " \"Bob in Python\": catppuccin_latte[\"blue\"],\n", " \"Bram in Rust\": catppuccin_latte[\"yellow\"],\n", " \"Brechtje in Python\": catppuccin_latte[\"green\"],\n", " \"Sander in Haskell\": catppuccin_latte[\"mauve\"],\n", " \"Vicky in Python\": catppuccin_latte[\"red\"],\n", "}\n", "\n", "def get_day(n : int) -> pd.DataFrame:\n", " return pd.DataFrame(compare.generate_day(n))\n", "\n", "def plot_day(day: int, log_scale=False, violin=False):\n", " df = get_day(day)\n", "\n", " # unit detection\n", " if df[\"time\"].max() < 1:\n", " unit = \"ms\"\n", " scale = 1000\n", " else:\n", " unit = \"s\"\n", " scale = 1\n", "\n", " # mutate in-place; nothing outside depends on it\n", " df[\"time_plot\"] = df[\"time\"] * scale\n", " df[\"author_lang\"] = df[\"author\"].str.capitalize() + \" in \" + df[\"lang\"]\n", "\n", " fig, ax = plt.subplots(figsize=(13, 8))\n", "\n", " plot_func = sns.violinplot if violin else sns.boxplot\n", " plot_func(\n", " data=df,\n", " x=\"part\",\n", " y=\"time_plot\",\n", " hue=\"author_lang\",\n", " ax=ax,\n", " palette=PALETTE,\n", " )\n", "\n", " if log_scale:\n", " ax.set_yscale(\"log\")\n", " ax.yaxis.set_major_locator(mticker.LogLocator(base=10, numticks=50))\n", " ax.yaxis.set_minor_locator(mticker.LogLocator(base=10, subs=range(1, 10)))\n", " \n", " # draw major (10^n) lines\n", " for y in ax.get_yticks():\n", " if y > 0 and ax.get_ylim()[0] <= y <= ax.get_ylim()[1]:\n", " ax.axhline(y, linestyle=\"--\", linewidth=0.6, color=\"gray\")\n", " \n", " # draw minor (1–9 × 10^n) lines\n", " for y in ax.get_yticks(minor=True):\n", " if y > 0 and ax.get_ylim()[0] <= y <= ax.get_ylim()[1]:\n", " ax.axhline(y, linestyle=\"--\", linewidth=0.4, color=\"gray\")\n", " else:\n", " ax.set_ylim(bottom=0)\n", " \n", " # double the density: add minor ticks at midpoints\n", " ax.yaxis.set_minor_locator(mticker.AutoMinorLocator(2))\n", " \n", " # draw major + minor lines\n", " for y in ax.get_yticks():\n", " ax.axhline(y, linestyle=\"--\", linewidth=0.6, color=\"gray\")\n", " for y in ax.get_yticks(minor=True):\n", " ax.axhline(y, linestyle=\"--\", linewidth=0.4, color=\"gray\")\n", "\n", " ax.set_xlabel(\"Puzzle Part\")\n", " ax.set_ylabel(f\"Execution Time ({unit})\")\n", " ax.set_title(f\"Advent of Code benchmarks day {day}\")\n", "\n", " ax.legend(title=\"Made by\")\n", " plt.tight_layout()\n", " plt.savefig(f\"img/day{day}.png\")\n", " plt.show()\n" ] }, { "cell_type": "markdown", "id": "212261b5-9a1b-4843-ac32-9f56f604cddb", "metadata": {}, "source": [ "## Day 1\n", "\n", "This puzzle incorporated a dial and counting the number of clicks on each dial." ] }, { "cell_type": "code", "execution_count": null, "id": "25a30802-1525-4d6b-8978-27aaf4d3843d", "metadata": {}, "outputs": [], "source": [ "plot_day(1, log_scale=True, violin=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "8452ddb0-f6d3-4a9b-aa2a-e27c12cc1c11", "metadata": {}, "outputs": [], "source": [ "plot_day(2, log_scale=True, violin=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "1d30b975-a467-4bd8-b042-d0efc75523b3", "metadata": {}, "outputs": [], "source": [ "plot_day(3, log_scale=False, violin=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "c91a9741-c1a4-4783-820a-b7ea92bac81a", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.11" } }, "nbformat": 4, "nbformat_minor": 5 }