Skip to content

Commit 5c241f9

Browse files
[wip] Add/pixi tasks (#1097)
* wip add pixi tasks * wip add pixi tasks * Add profiling skills and pixi profiling environment tasks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9b79444 commit 5c241f9

5 files changed

Lines changed: 155 additions & 2 deletions

File tree

.claude/skills/memray/SKILL.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
name: memray
3+
description: Profile the memory usage of a Python script using memray and visualize a temporal flamegraph in the browser. Use when the user wants to investigate memory consumption, find leaks, or understand allocation patterns.
4+
compatibility: Requires the pixi profiling environment (pixi run -e profiling). Supports Linux and macOS.
5+
allowed-tools: Bash(pixi run -e profiling memray-run:*) Bash(pixi run -e profiling memray-flame:*) Bash(open:*) Bash(xdg-open:*) Bash(python -m webbrowser:*)
6+
---
7+
8+
## Steps
9+
10+
1. Ask the user which script to profile (full or relative path).
11+
12+
2. Run the script under memray:
13+
14+
```bash
15+
pixi run -e profiling memray-run script.py
16+
```
17+
18+
This produces a binary file named `memray-script.py.<pid>.bin` in the current directory.
19+
20+
3. Generate the flamegraph HTML report from the `.bin` file:
21+
22+
```bash
23+
pixi run -e profiling memray-flame memray-script.py.<pid>.bin
24+
```
25+
26+
Replace `<pid>` with the actual PID shown in the filename. This writes `memray-flamegraph-script.py.<pid>.html`.
27+
28+
4. Open the report in the browser:
29+
- macOS: `open memray-flamegraph-script.py.<pid>.html`
30+
- Linux: `xdg-open memray-flamegraph-script.py.<pid>.html`
31+
- Either: `python -m webbrowser memray-flamegraph-script.py.<pid>.html`
32+
33+
## Notes
34+
35+
- The `--temporal` flag (included in `memray-flame`) shows memory over time, not just peak — use this to spot leaks and allocation bursts.
36+
- To find the `.bin` file if unsure of the name: `ls memray-*.bin`
37+
- To compare runs, save the previous report: `cp memray-flamegraph-script.py.<pid>.html memray-flamegraph-before.html`

.claude/skills/profimp/SKILL.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
name: profimp
3+
description: Profile Python import time using profimp and open a waterfall HTML report. Use when investigating slow startup or wanting to identify which imports are most expensive.
4+
compatibility: Requires profimp (available as a pixi dependency). macOS or Linux.
5+
allowed-tools: Bash(profimp:*) Bash(open:*) Bash(xdg-open:*) Bash(python -m webbrowser:*)
6+
---
7+
8+
## Steps
9+
10+
1. Ask what to profile. Suggest common patterns for this repo:
11+
- `import spatialdata`
12+
- `from spatialdata import SpatialData`
13+
- `from spatialdata_io import xenium`
14+
15+
2. Run:
16+
17+
```bash
18+
profimp --html "<import_stmt>" > /tmp/profimp.html
19+
```
20+
21+
3. Open the report:
22+
- macOS: `open /tmp/profimp.html`
23+
- Linux: `xdg-open /tmp/profimp.html`
24+
- Either: `python -m webbrowser /tmp/profimp.html`
25+
26+
## Notes
27+
28+
- The report is a waterfall chart showing every sub-import and its timing.
29+
- To compare before/after: `cp /tmp/profimp.html /tmp/profimp-before.html` before re-running.
30+
- `pixi run python -m profimp` also works if `profimp` is not on PATH.

.claude/skills/pyspy/SKILL.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
name: pyspy
3+
description: Profile the execution time of a Python script using py-spy and visualize the result with speedscope. Use when the user wants to benchmark performance, find slow code paths, or profile CPU time.
4+
compatibility: Requires the pixi profiling environment (pixi run -e profiling). Speedscope must be installed separately (npm install -g speedscope). sudo is required on macOS.
5+
allowed-tools: Bash(pixi run -e profiling pyspy:*) Bash(pixi run -e profiling speedscope:*) Bash(sudo pixi run -e profiling pyspy:*)
6+
---
7+
8+
## Steps
9+
10+
1. Ask the user which script to profile (full or relative path).
11+
12+
2. Run py-spy to record the profile. The output is always written to `profile.speedscope.json` in the current directory.
13+
14+
**Linux** (no sudo needed):
15+
16+
```bash
17+
pixi run -e profiling pyspy script.py
18+
```
19+
20+
**macOS** (sudo required — py-spy needs to attach to the process):
21+
22+
```bash
23+
sudo pixi run -e profiling pyspy script.py
24+
```
25+
26+
If sudo fails to find the pixi environment, use absolute paths:
27+
28+
```bash
29+
sudo /path/to/.pixi/envs/profiling/bin/py-spy record --gil \
30+
-o profile.speedscope.json --format speedscope \
31+
-- /path/to/.pixi/envs/profiling/bin/python script.py
32+
```
33+
34+
3. Open the result in speedscope:
35+
```bash
36+
pixi run -e profiling speedscope
37+
```
38+
This opens `profile.speedscope.json` in the browser via the local speedscope CLI.
39+
40+
## Notes
41+
42+
- If the speedscope view is blank, switch threads using the thread selector in the top-right corner.
43+
- To save a profile before overwriting: `cp profile.speedscope.json profile-before.speedscope.json`
44+
- `--gil` records only time when the GIL is held (Python-level CPU time). Drop it to include C extension time.
45+
- speedscope must be installed globally: `npm install -g speedscope`

.gitignore

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,18 @@ spatialdata-sandbox
4646
# version file
4747
_version.py
4848

49-
# other
50-
node_modules/
49+
# agents configurations
50+
.claude/settings.local.json
5151

52+
# benchmarking and profiling
5253
.asv/
54+
profile.speedscope.json
55+
56+
# other
57+
node_modules/
5358

5459
.mypy_cache
5560
.ruff_cache
5661
uv.lock
62+
pixi.lock
63+

pyproject.toml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,37 @@ convention = "numpy"
210210

211211
# pyupgrade typing rewrite TODO: remove at some point from per-file ignore
212212
# "UP006", "UP007"
213+
214+
[tool.pixi.workspace]
215+
channels = ["conda-forge"]
216+
platforms = ["osx-arm64", "linux-64"]
217+
218+
[tool.pixi.dependencies]
219+
proj = "*"
220+
221+
[tool.pixi.tasks]
222+
test = "pytest"
223+
test-parallel = "pytest -n auto --dist worksteal"
224+
pre-commit = "pre-commit run"
225+
pre-commit-all = "pre-commit run --all-files"
226+
227+
[tool.pixi.feature.profiling.dependencies]
228+
py-spy = "*"
229+
230+
[tool.pixi.feature.profiling.pypi-dependencies]
231+
spatialdata = { path = ".", editable = true }
232+
profimp = "*"
233+
memray = "*"
234+
235+
[tool.pixi.feature.profiling.tasks]
236+
# Usage: pixi run -e profiling pyspy script.py (prefix with sudo on macOS)
237+
pyspy = "py-spy record --gil -o profile.speedscope.json --format speedscope -- python"
238+
# Usage: pixi run -e profiling speedscope
239+
speedscope = "npx --yes speedscope profile.speedscope.json"
240+
# Usage: pixi run -e profiling memray-run script.py
241+
memray-run = "memray run"
242+
# Usage: pixi run -e profiling memray-flame memray-script.py.<pid>.bin
243+
memray-flame = "memray flamegraph --temporal"
244+
245+
[tool.pixi.environments]
246+
profiling = { features = ["profiling"], solve-group = "default" }

0 commit comments

Comments
 (0)