{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# scalene\n", "\n", "scalene creates profiles for CPU and memory very quickly. The overhead is usually very low at 10–20%.\n", "\n", "
\n", "\n", "**See also:**\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 and WSL:\n", "\n", "``` bash\n", "$ uv add scalene\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. An example programme for profiling" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2026-05-18T17:04:36.221310Z", "iopub.status.busy": "2026-05-18T17:04:36.221103Z", "iopub.status.idle": "2026-05-18T17:04:36.259230Z", "shell.execute_reply": "2026-05-18T17:04:36.258890Z", "shell.execute_reply.started": "2026-05-18T17:04:36.221283Z" } }, "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. Load scalene" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2026-05-18T17:04:36.259743Z", "iopub.status.busy": "2026-05-18T17:04:36.259608Z", "iopub.status.idle": "2026-05-18T17:04:37.522493Z", "shell.execute_reply": "2026-05-18T17:04:37.522197Z", "shell.execute_reply.started": "2026-05-18T17:04:36.259733Z" } }, "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. To profile in line mode, use\n", "`%scrun [options] statement`. To profile in cell mode, use `%%scalene\n", "[options]` followed by your code.\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. Profile with only one line of code" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2026-05-18T17:04:37.523138Z", "iopub.status.busy": "2026-05-18T17:04:37.523047Z", "iopub.status.idle": "2026-05-18T17:04:45.729367Z", "shell.execute_reply": "2026-05-18T17:04:45.728166Z", "shell.execute_reply.started": "2026-05-18T17:04:37.523130Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\n", "Scalene: profile saved to scalene-profile.json\n", " To view in browser: scalene view\n", " To view in terminal: scalene view --cli\n" ] }, { "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": [ "Create a reduced profile (only rows with non-zero counts)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2026-05-18T17:04:45.731819Z", "iopub.status.busy": "2026-05-18T17:04:45.731127Z", "iopub.status.idle": "2026-05-18T17:04:53.755214Z", "shell.execute_reply": "2026-05-18T17:04:53.754652Z", "shell.execute_reply.started": "2026-05-18T17:04:45.731768Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\n", "Scalene: profile saved to scalene-profile.json\n", " To view in browser: scalene view\n", " To view in terminal: scalene view --cli\n" ] }, { "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": [ "For a complete list of options, contact:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2026-05-18T17:04:53.756181Z", "iopub.status.busy": "2026-05-18T17:04:53.755814Z", "iopub.status.idle": "2026-05-18T17:04:53.768919Z", "shell.execute_reply": "2026-05-18T17:04:53.767045Z", "shell.execute_reply.started": "2026-05-18T17:04:53.756146Z" } }, "outputs": [ { "data": { "text/html": [ "
usage: scalene run [-h] [-o OUTFILE] [--cpu-only] [-c CONFIG_FILE]\n",
       "                   [--help-advanced]\n",
       "\n",
       "Profile a Python program with Scalene.\n",
       "\n",
       "examples:\n",
       "  % scalene run prog.py                 # profile, save to scalene-profile.json\n",
       "  % scalene run -o my.json prog.py      # save to custom file\n",
       "  % scalene run --cpu-only prog.py      # profile CPU only (faster)\n",
       "  % scalene run -c scalene.yaml prog.py # load options from config file\n",
       "  % scalene run prog.py --- --arg       # pass args to program\n",
       "  % scalene run --help-advanced         # show advanced options\n",
       "\n",
       "options:\n",
       "  -h, --help            show this help message and exit\n",
       "  -o, --outfile OUTFILE\n",
       "                        output file (default: scalene-profile.json)\n",
       "  --cpu-only            only profile CPU time (no memory/GPU)\n",
       "  -c, --config CONFIG_FILE\n",
       "                        load options from YAML config file\n",
       "  --help-advanced       show advanced options\n",
       "\n",
       "
\n" ], "text/plain": [ "\u001b[1;34musage:\u001b[0m \u001b[1;35mscalene\u001b[0m run [-h] [-o OUTFILE] [--cpu-only] [-c CONFIG_FILE]\n", " [--help-advanced]\n", "\n", "Profile a Python program with Scalene.\n", "\n", "examples:\n", " % scalene run prog.py # profile, save to scalene-profile.json\n", " % scalene run -o my.json prog.py # save to custom file\n", " % scalene run --cpu-only prog.py # profile CPU only (faster)\n", " % scalene run -c scalene.yaml prog.py # load options from config file\n", " % scalene run prog.py --- --arg # pass args to program\n", " % scalene run --help-advanced # show advanced options\n", "\n", "\u001b[1;34moptions:\u001b[0m\n", " \u001b[1;32m-h\u001b[0m, \u001b[1;36m--help\u001b[0m show this help message and exit\n", " \u001b[1;32m-o\u001b[0m, \u001b[1;36m--outfile\u001b[0m \u001b[1;33mOUTFILE\u001b[0m\n", " output file (default: scalene-profile.json)\n", " \u001b[1;36m--cpu-only\u001b[0m only profile CPU time (no memory/GPU)\n", " \u001b[1;32m-c\u001b[0m, \u001b[1;36m--config\u001b[0m \u001b[1;33mCONFIG_FILE\u001b[0m\n", " load options from YAML config file\n", " \u001b[1;36m--help-advanced\u001b[0m show advanced options\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%scrun --help" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Profile with more than one line of code in a cell" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.status.busy": "2026-05-18T17:04:53.769564Z", "iopub.status.idle": "2026-05-18T17:04:53.770073Z", "shell.execute_reply": "2026-05-18T17:04:53.769871Z", "shell.execute_reply.started": "2026-05-18T17:04:53.769838Z" } }, "outputs": [], "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.13 Kernel", "language": "python", "name": "python313" }, "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.13.0" }, "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 }