Skip to content

Scalene: Line-Level CPU and Memory Profiler

Scalene is a sampling profiler that reports CPU time and memory activity by source line and function. It runs inside the target process, combining timing estimates with allocation and copying measurements to distinguish expensive Python code from work performed by native libraries.

Unlike py-spy and Austin, Scalene requires starting the program under the profiler. It suits local diagnosis when a source-level report is more useful than attaching to an existing production process. Compare Python profilers for the alternatives.

Install alongside project dependencies

In an existing uv project:

uv add --dev scalene

The --dev flag marks Scalene as a development dependencyA package needed during development (testing, linting, formatting) that is not shipped to users of your project. Installed with the --dev flag. , keeping it out of production installs. uv adds Scalene to the development dependency group and installs it in the project’s virtual environment, alongside the application’s dependencies.

Scalene publishes packages for Linux, macOS, and Windows. Its package metadata requires Python 3.8 or newer, excluding Python 3.11.0; free-threaded builds have dedicated wheels for Python 3.13 and 3.14. Wheel availability and dependency compatibility vary by platform and interpreter. On Python 3.13t, the release notes require pydantic-core<=2.46.5; the PyPI file list lists available wheels.

Record and reopen a profile

For an existing program saved as script.py, run:

uv run scalene run script.py

uv run executes the command inside the project’s virtual environment, ensuring all dependencies are installed first. Scalene runs the program, then saves its measurements to scalene-profile.json in the current directory. Workloads must run long enough to collect samples; an empty profile does not establish that the program has no hotspots.

Display the saved report in the terminal:

uv run scalene view --cli

The output annotates source lines with timing and memory columns. To export a report with its viewer assets embedded:

uv run scalene view --standalone

This writes scalene-profile.html, which opens locally without fetching the viewer’s assets from the internet.

Option Effect
run --cpu-only Collect CPU measurements without memory or GPU profiling
run -o results.json Save measurements under a specified filename
run --profile-all Include source outside the entry-point directory, including libraries
view results.json Open a specified saved profile

Interpret the measurements

Report Meaning
Python, native, and system time Estimated time attributed to Python execution, native code, and system activity
Memory Sampled allocation activity, per-line memory growth, and memory trends
Copy volume Bytes copied through observed copying operations, useful when data crosses Python/native boundaries
Await time Wall-clock time attributed to the source line where a coroutine waits, with mean and peak concurrent waiters
Stack views Combined Python/native call paths and a timeline for relating activity to the run

Memory allocation measurements differ from resident memory, the physical pages currently held by the process. Austin’s memory mode measures changes in residency; the two reports answer different questions.

Async waits measure latency, not CPU consumption. A line with substantial waiting time may be waiting on a database or another task rather than performing expensive computation.

GPU measurements depend on the backend and accounting available on the machine. The project README documents NVIDIA GPU reporting; a utilization percentage is not a trace of individual GPU kernels. Per-process accounting and device-wide utilization must remain distinct when other processes share a GPU.

Account for attribution limits

The Python/native split is an estimate. Issue #428 reports misleading attribution in multithreaded code; the maintainer explains that worker threads use a different attribution method from the main thread. Validate a surprising split against the workload and available native-stack evidence before treating it as a reason to rewrite code.

Native stack capture is unavailable on Windows. On Apple M4 and newer chips with SME instructions, Scalene disables native stack capture to avoid a signal-handling problem that corrupts numerical state. CPU and line profiling use a separate sampling path on those machines, so the availability of line reports does not imply that native stack views are available.

Sampling does not count every call or allocation. Short operations may receive few samples, and profiling changes the workload’s execution costs. Compare repeated runs of the same workload when evaluating an optimization.

Request optional optimization suggestions

The local viewer works without a model provider. Its optional optimization controls send source text and measured line metrics to the selected provider, such as OpenAI, Amazon Bedrock, Azure, or a local model served through Ollama.

A local model keeps those requests on its configured endpoint; selecting a hosted provider sends them to that provider. Suggestions propose code changes, so correctness checks and another measured run are still needed to establish an improvement.

Last updated on