Skip to content

Commit 87d5385

Browse files
authored
Overhauled CLI. (#963)
* Overhauled CLI. * Avoid profiling by system libraries by default. * Linter clean. * Updated CLI syntax. * Updated CLI syntax. * Updated. * Updated major version.
1 parent 3bd7237 commit 87d5385

18 files changed

Lines changed: 1238 additions & 459 deletions

.github/workflows/test-smoketests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747

4848
# Note: test/smoketest.py only handles single JSON, rather than multiple in sequence.
4949
- name: profile-interval smoke test
50-
run: python -m scalene --cli --profile-interval=2 test/testme.py
50+
run: python -m scalene run --profile-interval=2 test/testme.py && python -m scalene view --cli
5151

5252
- name: decorator smoke test
5353
run: python test/smoketest_profile_decorator.py
@@ -70,4 +70,4 @@ jobs:
7070
- name: -m invocation smoketest
7171
run: |
7272
python -m pip install git+https://github.com/sternj/import_stress_test
73-
python -m scalene --cli --- -m import_stress_test
73+
python -m scalene run --- -m import_stress_test && python -m scalene view --cli

CLAUDE.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,83 @@ Key runtime dependencies:
256256

257257
See `requirements.txt` for full list.
258258

259+
## CLI Structure
260+
261+
Scalene uses a verb-based CLI with two main subcommands:
262+
263+
```bash
264+
# Profile a program (saves to scalene-profile.json by default)
265+
scalene run [options] yourprogram.py
266+
267+
# View an existing profile
268+
scalene view [options] [profile.json]
269+
```
270+
271+
### Run Subcommand Options
272+
273+
```bash
274+
scalene run prog.py # profile, save to scalene-profile.json
275+
scalene run -o my.json prog.py # save to custom file
276+
scalene run --cpu-only prog.py # profile CPU only (faster)
277+
scalene run -c config.yaml prog.py # load options from config file
278+
scalene run prog.py --- --arg # pass args to program
279+
```
280+
281+
### View Subcommand Options
282+
283+
```bash
284+
scalene view # open in browser
285+
scalene view --cli # view in terminal
286+
scalene view --html # save to scalene-profile.html
287+
scalene view myprofile.json # open specific profile
288+
```
289+
290+
### YAML Configuration
291+
292+
Create a `scalene.yaml` file with options:
293+
294+
```yaml
295+
outfile: my-profile.json
296+
cpu-only: true
297+
profile-only: "mypackage,utils"
298+
cpu-percent-threshold: 5
299+
```
300+
301+
Load with: `scalene run -c scalene.yaml prog.py`
302+
303+
### Advanced Options
304+
305+
Use `scalene run --help-advanced` to see all options including:
306+
- `--profile-all` - profile all code, not just the target program
307+
- `--profile-only PATH` - only profile files containing these strings
308+
- `--profile-exclude PATH` - exclude files containing these strings
309+
- `--profile-system-libraries` - profile Python stdlib and installed packages (skipped by default)
310+
- `--gpu` - profile GPU time and memory
311+
- `--memory` - profile memory usage
312+
- `--stacks` - collect stack traces
313+
- `--profile-interval N` - output profiles every N seconds
314+
315+
### Smoke Tests
316+
317+
Smoke tests in `test/` use the new CLI syntax:
318+
319+
```python
320+
# test/smoketest.py
321+
cmd = [sys.executable, "-m", "scalene", "run", "-o", str(outfile), *rest, fname]
322+
```
323+
324+
### GitHub Workflows
325+
326+
Workflows in `.github/workflows/` use the new CLI:
327+
328+
```yaml
329+
# Profile with interval, then view
330+
- run: python -m scalene run --profile-interval=2 test/testme.py && python -m scalene view --cli
331+
332+
# Profile with module invocation
333+
- run: python -m scalene run --- -m import_stress_test && python -m scalene view --cli
334+
```
335+
259336
## Profiling Guide
260337

261338
See [Scalene-Agents.md](Scalene-Agents.md) for detailed information about interpreting Scalene's profiling output, including Python vs C time, memory metrics, and optimization strategies.

README.md

Lines changed: 149 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,75 @@ First, install <a href="https://marketplace.visualstudio.com/items?itemName=Emer
8080
Commonly used command-line options:
8181
</summary>
8282

83+
Scalene uses a verb-based command structure with two main commands: `run` (to profile) and `view` (to display results).
84+
85+
```console
86+
# Profile a program (saves to scalene-profile.json)
87+
scalene run your_prog.py
88+
python3 -m scalene run your_prog.py # equivalent alternative
89+
90+
# View a profile
91+
scalene view # open profile in browser
92+
scalene view --cli # view in terminal
93+
scalene view --html # save to scalene-profile.html
94+
95+
# Common profiling options
96+
scalene run --cpu-only your_prog.py # only profile CPU (faster)
97+
scalene run -o results.json your_prog.py # custom output filename
98+
scalene run -c config.yaml your_prog.py # load options from config file
99+
100+
# Pass arguments to your program (use --- separator)
101+
scalene run your_prog.py --- --arg1 --arg2
102+
103+
# Get help
104+
scalene --help # main help
105+
scalene run --help # profiling options
106+
scalene run --help-advanced # advanced profiling options
107+
scalene view --help # viewing options
108+
```
109+
110+
</details>
111+
112+
<details>
113+
<summary>
114+
Using a YAML configuration file:
115+
</summary>
116+
117+
You can store Scalene options in a YAML configuration file and load them with `-c` or `--config`:
118+
83119
```console
84-
scalene your_prog.py # full profile (outputs to web interface)
85-
python3 -m scalene your_prog.py # equivalent alternative
120+
scalene run -c scalene.yaml your_prog.py
121+
```
122+
123+
Example `scalene.yaml`:
124+
125+
```yaml
126+
# Output options
127+
outfile: my-profile.json
86128

87-
scalene --cli your_prog.py # use the command-line only (no web interface)
129+
# Profiling mode (use only one)
130+
cpu-only: true # CPU profiling only (faster)
131+
# gpu: true # Include GPU profiling
132+
# memory: true # Include memory profiling
88133

89-
scalene --cpu your_prog.py # only profile CPU
90-
scalene --cpu --gpu your_prog.py # only profile CPU and GPU
91-
scalene --cpu --gpu --memory your_prog.py # profile everything (same as no options)
134+
# Filter what gets profiled
135+
profile-only: "mypackage,mymodule" # Only profile these paths
136+
profile-exclude: "tests,venv" # Exclude these paths
137+
profile-all: false # Profile all code, not just target
92138

93-
scalene --reduced-profile your_prog.py # only profile lines with significant usage
94-
scalene --profile-interval 5.0 your_prog.py # output a new profile every five seconds
139+
# Performance tuning
140+
cpu-percent-threshold: 1 # Min CPU% to report (default: 1)
141+
cpu-sampling-rate: 0.01 # Sampling interval in seconds
142+
malloc-threshold: 100 # Min allocations to report
95143

96-
scalene (Scalene options) --- your_prog.py (...) # use --- to tell Scalene to ignore options after that point
97-
scalene --help # lists all options
144+
# Other options
145+
use-virtual-time: false # Measure CPU time only (not I/O)
146+
stacks: false # Collect stack traces
147+
memory-leak-detector: true # Detect likely memory leaks
98148
```
99149
150+
Command-line arguments override config file settings.
151+
100152
</details>
101153
102154
<details>
@@ -259,57 +311,86 @@ scalene test/testme.py
259311
</summary>
260312

261313
```console
262-
% scalene --help
263-
usage: scalene [-h] [--outfile OUTFILE] [--html] [--reduced-profile]
264-
[--profile-interval PROFILE_INTERVAL] [--cpu-only]
265-
[--profile-all] [--profile-only PROFILE_ONLY]
266-
[--use-virtual-time]
267-
[--cpu-percent-threshold CPU_PERCENT_THRESHOLD]
268-
[--cpu-sampling-rate CPU_SAMPLING_RATE]
269-
[--malloc-threshold MALLOC_THRESHOLD]
270-
271-
Scalene: a high-precision CPU and memory profiler.
272-
https://github.com/plasma-umass/scalene
273-
274-
command-line:
275-
% scalene [options] yourprogram.py
276-
or
277-
% python3 -m scalene [options] yourprogram.py
278-
279-
in Jupyter, line mode:
280-
%scrun [options] statement
281-
282-
in Jupyter, cell mode:
283-
%%scalene [options]
284-
code...
285-
code...
286-
287-
optional arguments:
288-
-h, --help show this help message and exit
289-
--outfile OUTFILE file to hold profiler output (default: stdout)
290-
--html output as HTML (default: text)
291-
--reduced-profile generate a reduced profile, with non-zero lines only (default: False)
292-
--profile-interval PROFILE_INTERVAL
293-
output profiles every so many seconds (default: inf)
294-
--cpu-only only profile CPU time (default: profile CPU, memory, and copying)
295-
--profile-all profile all executed code, not just the target program (default: only the target program)
296-
--profile-only PROFILE_ONLY
297-
profile only code in filenames that contain the given strings, separated by commas (default: no restrictions)
298-
--use-virtual-time measure only CPU time, not time spent in I/O or blocking (default: False)
299-
--cpu-percent-threshold CPU_PERCENT_THRESHOLD
300-
only report profiles with at least this percent of CPU time (default: 1%)
301-
--cpu-sampling-rate CPU_SAMPLING_RATE
302-
CPU sampling rate (default: every 0.01s)
303-
--malloc-threshold MALLOC_THRESHOLD
304-
only report profiles with at least this many allocations (default: 100)
305-
306-
When running Scalene in the background, you can suspend/resume profiling
307-
for the process ID that Scalene reports. For example:
308-
309-
% python3 -m scalene [options] yourprogram.py &
310-
Scalene now profiling process 12345
311-
to suspend profiling: python3 -m scalene.profile --off --pid 12345
312-
to resume profiling: python3 -m scalene.profile --on --pid 12345
314+
% scalene --help
315+
Scalene: a high-precision CPU and memory profiler, version 1.5.51 (2025.01.29)
316+
https://github.com/plasma-umass/scalene
317+
318+
commands:
319+
run Profile a Python program (saves to scalene-profile.json)
320+
view View an existing profile in browser or terminal
321+
322+
examples:
323+
% scalene run your_program.py # profile, save to scalene-profile.json
324+
% scalene view # view scalene-profile.json in browser
325+
% scalene view --cli # view profile in terminal
326+
327+
in Jupyter, line mode:
328+
%scrun [options] statement
329+
330+
in Jupyter, cell mode:
331+
%%scalene [options]
332+
your code here
333+
334+
% scalene run --help
335+
Profile a Python program with Scalene.
336+
337+
examples:
338+
% scalene run prog.py # profile, save to scalene-profile.json
339+
% scalene run -o my.json prog.py # save to custom file
340+
% scalene run --cpu-only prog.py # profile CPU only (faster)
341+
% scalene run -c scalene.yaml prog.py # load options from config file
342+
% scalene run prog.py --- --arg # pass args to program
343+
% scalene run --help-advanced # show advanced options
344+
345+
options:
346+
-h, --help show this help message and exit
347+
-o, --outfile OUTFILE output file (default: scalene-profile.json)
348+
--cpu-only only profile CPU time (no memory/GPU)
349+
-c, --config FILE load options from YAML config file
350+
--help-advanced show advanced options
351+
352+
% scalene run --help-advanced
353+
Advanced options for scalene run:
354+
355+
background profiling:
356+
Use --off to start with profiling disabled, then control it from another terminal:
357+
% scalene run --off prog.py # start with profiling off
358+
% python3 -m scalene.profile --on --pid <PID> # resume profiling
359+
% python3 -m scalene.profile --off --pid <PID> # suspend profiling
360+
361+
options:
362+
--profile-all profile all code, not just the target program
363+
--profile-only PATH only profile files containing these strings (comma-separated)
364+
--profile-exclude PATH exclude files containing these strings (comma-separated)
365+
--profile-system-libraries profile Python stdlib and installed packages (default: skip)
366+
--gpu profile GPU time and memory
367+
--memory profile memory usage
368+
--stacks collect stack traces
369+
--profile-interval N output profiles every N seconds (default: inf)
370+
--use-virtual-time measure only CPU time, not I/O or blocking
371+
--cpu-percent-threshold N only report lines with at least N% CPU (default: 1%)
372+
--cpu-sampling-rate N CPU sampling rate in seconds (default: 0.01)
373+
--allocation-sampling-window N allocation sampling window in bytes
374+
--malloc-threshold N only report lines with at least N allocations (default: 100)
375+
--program-path PATH directory containing code to profile
376+
--memory-leak-detector EXPERIMENTAL: report likely memory leaks
377+
--on start with profiling on (default)
378+
--off start with profiling off
379+
380+
% scalene view --help
381+
View an existing Scalene profile.
382+
383+
examples:
384+
% scalene view # open in browser
385+
% scalene view --cli # view in terminal
386+
% scalene view --html # save to scalene-profile.html
387+
% scalene view myprofile.json # open specific profile in browser
388+
389+
options:
390+
-h, --help show this help message and exit
391+
--cli display profile in the terminal
392+
--html save to scalene-profile.html (no browser)
393+
-r, --reduced only show lines with activity (--cli mode)
313394
```
314395
</details>
315396

@@ -410,7 +491,11 @@ Can I use Scalene with PyTest?
410491

411492
**A:** Yes! You can run it as follows (for example):
412493

413-
`python3 -m scalene --- -m pytest your_test.py`
494+
`scalene run -m pytest your_test.py`
495+
496+
or
497+
498+
`python3 -m scalene run -m pytest your_test.py`
414499

415500
</details>
416501

@@ -424,15 +509,15 @@ Is there any way to get shorter profiles or do more targeted profiling?
424509
1. Use `--reduced-profile` to include only lines and files with memory/CPU/GPU activity.
425510
2. Use `--profile-only` to include only filenames containing specific strings (as in, `--profile-only foo,bar,baz`).
426511
3. Decorate functions of interest with `@profile` to have Scalene report _only_ those functions.
427-
4. Turn profiling on and off programmatically by importing Scalene profiler (`from scalene import scalene_profiler`) and then turning profiling on and off via `scalene_profiler.start()` and `scalene_profiler.stop()`. By default, Scalene runs with profiling on, so to delay profiling until desired, use the `--off` command-line option (`python3 -m scalene --off yourprogram.py`).
512+
4. Turn profiling on and off programmatically by importing Scalene profiler (`from scalene import scalene_profiler`) and then turning profiling on and off via `scalene_profiler.start()` and `scalene_profiler.stop()`. By default, Scalene runs with profiling on, so to delay profiling until desired, use the `--off` command-line option (`scalene run --off yourprogram.py`).
428513
</details>
429514

430515
<details>
431516
<summary>
432517
How do I run Scalene in PyCharm?
433518
</summary>
434519

435-
**A:** In PyCharm, you can run Scalene at the command line by opening the terminal at the bottom of the IDE and running a Scalene command (e.g., `python -m scalene <your program>`). Use the options `--cli`, `--html`, and `--outfile <your output.html>` to generate an HTML file that you can then view in the IDE.
520+
**A:** In PyCharm, you can run Scalene at the command line by opening the terminal at the bottom of the IDE and running a Scalene command (e.g., `scalene run <your program>`). Then use `scalene view --html` to generate an HTML file (`scalene-profile.html`) that you can view in the IDE.
436521
</details>
437522

438523
<details>

0 commit comments

Comments
 (0)