{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# scalene\n", "\n", "scalene erstellt sehr schnell Profile für CPU und Arbeitsspeicher. Dabei ist der Overhead üblicherweise mit 10–20% sehr gering.\n", "\n", "
\n", "\n", "**Siehe auch**\n", "\n", "* [GitHub](https://github.com/emeryberger/Scalene)\n", "* [PyPI](https://pypi.org/project/scalene/)\n", "* [scalene-paper.pdf](https://github.com/plasma-umass/scalene/blob/master/docs/scalene-paper.pdf)\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installation\n", "\n", "Linux, MacOS und WSL:\n", "\n", "```bash\n", "$ uv add scalene\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Verwendung" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Ein Beispielprogramm zum Profilieren" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2026-05-21T21:38:36.600414Z", "iopub.status.busy": "2026-05-21T21:38:36.600264Z", "iopub.status.idle": "2026-05-21T21:38:36.726396Z", "shell.execute_reply": "2026-05-21T21:38:36.725781Z", "shell.execute_reply.started": "2026-05-21T21:38:36.600398Z" } }, "outputs": [], "source": [ "import numpy as np\n", "\n", "\n", "def profile_me():\n", " for _i in range(6):\n", " x = np.array(range(10**7))\n", " rng = np.random.default_rng()\n", " y = np.array(rng.uniform(0, 100, size=(10**8)))\n", " return x, y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. Scalene laden" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2026-05-21T21:38:36.730459Z", "iopub.status.busy": "2026-05-21T21:38:36.727323Z", "iopub.status.idle": "2026-05-21T21:38:36.914879Z", "shell.execute_reply": "2026-05-21T21:38:36.914621Z", "shell.execute_reply.started": "2026-05-21T21:38:36.730438Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalene extension successfully loaded. Note: Scalene currently only\n", "supports CPU+GPU profiling inside Jupyter notebooks. For full Scalene\n", "profiling, use the command line version.\n", "\n", "NOTE: in Jupyter notebook on MacOS, Scalene cannot profile child\n", "processes. Do not run to try Scalene with multiprocessing in Jupyter\n", "Notebook.\n" ] } ], "source": [ "%load_ext scalene" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. Profil mit nur einer Codezeile" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2026-05-21T21:38:36.915679Z", "iopub.status.busy": "2026-05-21T21:38:36.915540Z", "iopub.status.idle": "2026-05-21T21:38:45.200674Z", "shell.execute_reply": "2026-05-21T21:38:45.199677Z", "shell.execute_reply.started": "2026-05-21T21:38:36.915669Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%scrun profile_me()\n", "import numpy as np\n", "\n", "\n", "def profile_me():\n", " for _i in range(6):\n", " x = np.array(range(10**7))\n", " rng = np.random.default_rng()\n", " y = np.array(rng.uniform(0, 100, size=(10**8)))\n", " return x, y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Erzeugen Sie ein reduziertes Profil (nur Zeilen mit Zählungen ungleich Null)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2026-05-21T21:38:45.203313Z", "iopub.status.busy": "2026-05-21T21:38:45.202729Z", "iopub.status.idle": "2026-05-21T21:38:53.459120Z", "shell.execute_reply": "2026-05-21T21:38:53.457898Z", "shell.execute_reply.started": "2026-05-21T21:38:45.203270Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%scrun --reduced-profile profile_me()\n", "import numpy as np\n", "\n", "\n", "def profile_me():\n", " for _i in range(6):\n", " x = np.array(range(10**7))\n", " rng = np.random.default_rng()\n", " y = np.array(rng.uniform(0, 100, size=(10**8)))\n", " return x, y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eine vollständige Liste der Optionen erhalter ihr mit:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2026-05-21T21:38:53.460434Z", "iopub.status.busy": "2026-05-21T21:38:53.460216Z", "iopub.status.idle": "2026-05-21T21:38:53.488169Z", "shell.execute_reply": "2026-05-21T21:38:53.487123Z", "shell.execute_reply.started": "2026-05-21T21:38:53.460418Z" } }, "outputs": [ { "data": { "text/html": [ "
usage: scalene [-h] [--version] [--column-width COLUMN_WIDTH]\n",
       "               [--outfile OUTFILE] [--html] [--json] [--cli] [--stacks]\n",
       "               [--web] [--viewer] [--reduced-profile]\n",
       "               [--profile-interval PROFILE_INTERVAL] [--cpu] [--cpu-only]\n",
       "               [--gpu] [--memory] [--profile-all]\n",
       "               [--profile-only PROFILE_ONLY]\n",
       "               [--profile-exclude PROFILE_EXCLUDE] [--use-virtual-time]\n",
       "               [--cpu-percent-threshold CPU_PERCENT_THRESHOLD]\n",
       "               [--cpu-sampling-rate CPU_SAMPLING_RATE]\n",
       "               [--allocation-sampling-window ALLOCATION_SAMPLING_WINDOW]\n",
       "               [--malloc-threshold MALLOC_THRESHOLD]\n",
       "               [--program-path PROGRAM_PATH] [--memory-leak-detector]\n",
       "               [--on | --off]\n",
       "\n",
       "Scalene: a high-precision CPU and memory profiler, version 1.5.24 (2023.08.09)\n",
       "https://github.com/plasma-umass/scalene\n",
       "\n",
       "command-line:\n",
       "  % scalene [options] your_program.py [--- --your_program_args] \n",
       "or\n",
       "  % python3 -m scalene [options] your_program.py [--- --your_program_args] \n",
       "\n",
       "in Jupyter, line mode:\n",
       "  %scrun [options] statement\n",
       "\n",
       "in Jupyter, cell mode:\n",
       "  %%scalene [options]\n",
       "   your code here\n",
       "\n",
       "\n",
       "options:\n",
       "  -h, --help            show this help message and exit\n",
       "  --version             prints the version number for this release of Scalene and exits\n",
       "  --column-width COLUMN_WIDTH\n",
       "                        Column width for profile output (default: 132)\n",
       "  --outfile OUTFILE     file to hold profiler output (default: stdout)\n",
       "  --html                output as HTML (default: web)\n",
       "  --json                output as JSON (default: web)\n",
       "  --cli                 forces use of the command-line\n",
       "  --stacks              collect stack traces\n",
       "  --web                 opens a web tab to view the profile (saved as 'profile.html')\n",
       "  --viewer              only opens the web UI (https://plasma-umass.org/scalene-gui/)\n",
       "  --reduced-profile     generate a reduced profile, with non-zero lines only (default: False)\n",
       "  --profile-interval PROFILE_INTERVAL\n",
       "                        output profiles every so many seconds (default: inf)\n",
       "  --cpu                 profile CPU time (default:  True )\n",
       "  --cpu-only            profile CPU time (deprecated: use --cpu )\n",
       "  --gpu                 profile GPU time and memory (default: False )\n",
       "  --memory              profile memory (default: True )\n",
       "  --profile-all         profile all executed code, not just the target program (default: only the target program)\n",
       "  --profile-only PROFILE_ONLY\n",
       "                        profile only code in filenames that contain the given strings, separated by commas \n",
       "(default: no restrictions)\n",
       "  --profile-exclude PROFILE_EXCLUDE\n",
       "                        do not profile code in filenames that contain the given strings, separated by commas \n",
       "(default: no restrictions)\n",
       "  --use-virtual-time    measure only CPU time, not time spent in I/O or blocking (default: False)\n",
       "  --cpu-percent-threshold CPU_PERCENT_THRESHOLD\n",
       "                        only report profiles with at least this percent of CPU time (default: 1%)\n",
       "  --cpu-sampling-rate CPU_SAMPLING_RATE\n",
       "                        CPU sampling rate (default: every 0.01s)\n",
       "  --allocation-sampling-window ALLOCATION_SAMPLING_WINDOW\n",
       "                        Allocation sampling window size, in bytes (default: 10485767 bytes)\n",
       "  --malloc-threshold MALLOC_THRESHOLD\n",
       "                        only report profiles with at least this many allocations (default: 100)\n",
       "  --program-path PROGRAM_PATH\n",
       "                        The directory containing the code to profile (default: the path to the profiled program)\n",
       "  --memory-leak-detector\n",
       "                        EXPERIMENTAL: report likely memory leaks (default: True)\n",
       "  --on                  start with profiling on (default)\n",
       "  --off                 start with profiling off\n",
       "\n",
       "When running Scalene in the background, you can suspend/resume profiling\n",
       "for the process ID that Scalene reports. For example:\n",
       "\n",
       "   % python3 -m scalene  yourprogram.py &\n",
       " Scalene now profiling process 12345\n",
       "   to suspend profiling: python3 -m scalene.profile --off --pid 12345\n",
       "   to resume profiling:  python3 -m scalene.profile --on  --pid 12345\n",
       "\n",
       "
\n" ], "text/plain": [ "usage: scalene \u001b[1m[\u001b[0m-h\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--version\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--column-width COLUMN_WIDTH\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--outfile OUTFILE\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--html\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--json\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--cli\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--stacks\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--web\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--viewer\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--reduced-profile\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--profile-interval PROFILE_INTERVAL\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--cpu\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--cpu-only\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--gpu\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--memory\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--profile-all\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--profile-only PROFILE_ONLY\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--profile-exclude PROFILE_EXCLUDE\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--use-virtual-time\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--cpu-percent-threshold CPU_PERCENT_THRESHOLD\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--cpu-sampling-rate CPU_SAMPLING_RATE\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--allocation-sampling-window ALLOCATION_SAMPLING_WINDOW\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--malloc-threshold MALLOC_THRESHOLD\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--program-path PROGRAM_PATH\u001b[1m]\u001b[0m \u001b[1m[\u001b[0m--memory-leak-detector\u001b[1m]\u001b[0m\n", " \u001b[1m[\u001b[0m--on | --off\u001b[1m]\u001b[0m\n", "\n", "\u001b[1mScalene\u001b[0m: a high-precision CPU and memory profiler, version \u001b[1;36m1.5\u001b[0m.\u001b[1;36m24\u001b[0m \u001b[1m(\u001b[0m\u001b[1;36m2023.08\u001b[0m.\u001b[1;36m09\u001b[0m\u001b[1m)\u001b[0m\n", "\u001b]8;id=593644;https://github.com/plasma-umass/scalene\u001b\\\u001b[4;94mhttps://github.com/plasma-umass/scalene\u001b[0m\u001b]8;;\u001b\\\n", "\n", "command-line:\n", " % \u001b[1mscalene \u001b[0m\u001b[1m[\u001b[0m\u001b[1moptions\u001b[0m\u001b[1m]\u001b[0m\u001b[1m your_program.py \u001b[0m\u001b[1m[\u001b[0m\u001b[1m--- --your_program_args\u001b[0m\u001b[1m]\u001b[0m\u001b[1m \u001b[0m\n", "or\n", " % \u001b[1mpython3 -m scalene \u001b[0m\u001b[1m[\u001b[0m\u001b[1moptions\u001b[0m\u001b[1m]\u001b[0m\u001b[1m your_program.py \u001b[0m\u001b[1m[\u001b[0m\u001b[1m--- --your_program_args\u001b[0m\u001b[1m]\u001b[0m\u001b[1m \u001b[0m\n", "\n", "in Jupyter, line mode:\n", "\u001b[1m %scrun \u001b[0m\u001b[1m[\u001b[0m\u001b[1moptions\u001b[0m\u001b[1m]\u001b[0m\u001b[1m statement\u001b[0m\n", "\n", "in Jupyter, cell mode:\n", "\u001b[1m %%scalene \u001b[0m\u001b[1m[\u001b[0m\u001b[1moptions\u001b[0m\u001b[1m]\u001b[0m\n", "\u001b[1m your code here\u001b[0m\n", "\n", "\n", "options:\n", " -h, --help show this help message and exit\n", " --version prints the version number for this release of Scalene and exits\n", " --column-width COLUMN_WIDTH\n", " Column width for profile output \u001b[1m(\u001b[0mdefault: \u001b[1;34m132\u001b[0m\u001b[1m)\u001b[0m\n", " --outfile OUTFILE file to hold profiler output \u001b[1m(\u001b[0mdefault: \u001b[34mstdout\u001b[0m\u001b[1m)\u001b[0m\n", " --html output as HTML \u001b[1m(\u001b[0mdefault: \u001b[34mweb\u001b[0m\u001b[1m)\u001b[0m\n", " --json output as JSON \u001b[1m(\u001b[0mdefault: \u001b[34mweb\u001b[0m\u001b[1m)\u001b[0m\n", " --cli forces use of the command-line\n", " --stacks collect stack traces\n", " --web opens a web tab to view the profile \u001b[1m(\u001b[0msaved as \u001b[32m'profile.html'\u001b[0m\u001b[1m)\u001b[0m\n", " --viewer only opens the web UI \u001b[1m(\u001b[0m\u001b[4;94mhttps://plasma-umass.org/scalene-gui/\u001b[0m\u001b[4;94m)\u001b[0m\n", " --reduced-profile generate a reduced profile, with non-zero lines only \u001b[1m(\u001b[0mdefault: \u001b[3;34mFalse\u001b[0m\u001b[1m)\u001b[0m\n", " --profile-interval PROFILE_INTERVAL\n", " output profiles every so many seconds \u001b[1m(\u001b[0mdefault: \u001b[34minf\u001b[0m\u001b[1m)\u001b[0m\n", " --cpu profile CPU time \u001b[1m(\u001b[0mdefault: \u001b[34m \u001b[0m\u001b[3;34mTrue\u001b[0m\u001b[34m \u001b[0m\u001b[1m)\u001b[0m\n", " --cpu-only profile CPU time \u001b[1m(\u001b[0m\u001b[31mdeprecated: use --cpu \u001b[0m\u001b[1m)\u001b[0m\n", " --gpu profile GPU time and memory \u001b[1m(\u001b[0mdefault: \u001b[3;34mFalse\u001b[0m\u001b[34m \u001b[0m\u001b[1m)\u001b[0m\n", " --memory profile memory \u001b[1m(\u001b[0mdefault: \u001b[3;34mTrue\u001b[0m\u001b[34m \u001b[0m\u001b[1m)\u001b[0m\n", " --profile-all profile all executed code, not just the target program \u001b[1m(\u001b[0mdefault: \u001b[34monly the target program\u001b[0m\u001b[1m)\u001b[0m\n", " --profile-only PROFILE_ONLY\n", " profile only code in filenames that contain the given strings, separated by commas \n", "\u001b[1m(\u001b[0mdefault: \u001b[34mno restrictions\u001b[0m\u001b[1m)\u001b[0m\n", " --profile-exclude PROFILE_EXCLUDE\n", " do not profile code in filenames that contain the given strings, separated by commas \n", "\u001b[1m(\u001b[0mdefault: \u001b[34mno restrictions\u001b[0m\u001b[1m)\u001b[0m\n", " --use-virtual-time measure only CPU time, not time spent in I/O or blocking \u001b[1m(\u001b[0mdefault: \u001b[3;34mFalse\u001b[0m\u001b[1m)\u001b[0m\n", " --cpu-percent-threshold CPU_PERCENT_THRESHOLD\n", " only report profiles with at least this percent of CPU time \u001b[1m(\u001b[0mdefault: \u001b[1;34m1\u001b[0m\u001b[34m%\u001b[0m\u001b[1m)\u001b[0m\n", " --cpu-sampling-rate CPU_SAMPLING_RATE\n", " CPU sampling rate \u001b[1m(\u001b[0mdefault: every \u001b[1;34m0.\u001b[0m\u001b[34m01s\u001b[0m\u001b[1m)\u001b[0m\n", " --allocation-sampling-window ALLOCATION_SAMPLING_WINDOW\n", " Allocation sampling window size, in bytes \u001b[1m(\u001b[0mdefault: \u001b[1;34m10485767\u001b[0m\u001b[34m bytes\u001b[0m\u001b[1m)\u001b[0m\n", " --malloc-threshold MALLOC_THRESHOLD\n", " only report profiles with at least this many allocations \u001b[1m(\u001b[0mdefault: \u001b[1;34m100\u001b[0m\u001b[1m)\u001b[0m\n", " --program-path PROGRAM_PATH\n", " The directory containing the code to profile \u001b[1m(\u001b[0mdefault: \u001b[34mthe path to the profiled program\u001b[0m\u001b[1m)\u001b[0m\n", " --memory-leak-detector\n", " EXPERIMENTAL: report likely memory leaks \u001b[1m(\u001b[0mdefault: \u001b[3;34mTrue\u001b[0m\u001b[1m)\u001b[0m\n", " --on start with profiling on \u001b[1m(\u001b[0mdefault\u001b[1m)\u001b[0m\n", " --off start with profiling off\n", "\n", "When running Scalene in the background, you can suspend/resume profiling\n", "for the process ID that Scalene reports. For example:\n", "\n", " % python3 -m scalene yourprogram.py &\n", " Scalene now profiling process \u001b[1;36m12345\u001b[0m\n", " to suspend profiling: python3 -m scalene.profile --off --pid \u001b[1;36m12345\u001b[0m\n", " to resume profiling: python3 -m scalene.profile --on --pid \u001b[1;36m12345\u001b[0m\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%scrun --help" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Profil mit mehr als einer Codezeile in einer Zelle" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2026-05-21T21:39:17.710098Z", "iopub.status.busy": "2026-05-21T21:39:17.709661Z", "iopub.status.idle": "2026-05-21T21:39:19.807291Z", "shell.execute_reply": "2026-05-21T21:39:19.806704Z", "shell.execute_reply.started": "2026-05-21T21:39:17.710067Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%scalene --reduced-profile\n", "x = 0\n", "for _i in range(1000):\n", " for _j in range(1000):\n", " x += 1" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.11 Kernel", "language": "python", "name": "python311" }, "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.11.14" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }