# DECNET Profiling Five complementary lenses. Pick whichever answers the question you have. ## 1. Whole-process sampling — py-spy > **Note:** py-spy 0.4.1 (latest on PyPI as of 2026-04) does **not** yet support > Python 3.14, which DECNET currently runs on. Attaching fails with > *"No python processes found in process "* even when uvicorn is clearly > running. Use lenses 2–5 until upstream ships 3.14 support > (track https://github.com/benfred/py-spy/releases). The wrapper script aborts > with a clear message when it detects 3.14+. Attach to a running API and record a flamegraph for 30s. Requires `sudo` (Linux ptrace scope). ```bash ./scripts/profile/pyspy-attach.sh # auto-finds uvicorn pid sudo py-spy record -o profile.svg -p -d 30 --subprocesses ``` Other common failure modes (when py-spy *does* support your Python): - Attached to the Typer CLI PID, not the uvicorn worker PID (use `pgrep -f 'uvicorn decnet.web.api'`). - `kernel.yama.ptrace_scope=1` — run with `sudo` or `sudo sysctl kernel.yama.ptrace_scope=0`. - The API isn't actually running (a `--dry-run` deploy starts nothing). ## 2. Per-request flamegraphs — Pyinstrument Set the env flag, hit endpoints, find HTML flamegraphs under `./profiles/`. ```bash DECNET_PROFILE_REQUESTS=true decnet deploy --mode unihost --deckies 1 # in another shell: curl http://127.0.0.1:8000/api/v1/health open profiles/*.html ``` Off by default — zero overhead when the flag is unset. ## 3. Deterministic call graph — cProfile + snakeviz For one-shot profiling of CLI commands or scripts. ```bash ./scripts/profile/cprofile-cli.sh services # profiles `decnet services` snakeviz profiles/cprofile.prof ``` ## 4. Micro-benchmarks — pytest-benchmark Regression-gate repository hot paths. ```bash pytest -m bench tests/perf/ -n0 # SQLite backend (default) DECNET_DB_TYPE=mysql pytest -m bench tests/perf/ -n0 ``` Note: `-n0` disables xdist. `pytest-benchmark` refuses to measure under parallel workers, which is the project default (`-n logical --dist loadscope`). ## 5. Memory allocation — memray Hunt leaks and allocation hot spots in the API / workers. ```bash ./scripts/profile/memray-api.sh # runs uvicorn under memray memray flamegraph profiles/memray.bin ``` ## Viewing artifacts All profiling outputs land under `./profiles/`. Use the viewer wrapper to auto-pick the newest file and launch the right tool: ```bash ./scripts/profile/view.sh # newest artifact of any kind ./scripts/profile/view.sh cprofile # newest .prof -> snakeviz ./scripts/profile/view.sh memray # newest memray .bin -> flamegraph ./scripts/profile/view.sh pyinstrument # newest .html -> browser ./scripts/profile/view.sh path/to/file # explicit file # Memray view modes: VIEW=flamegraph ./scripts/profile/view.sh memray # default VIEW=table ./scripts/profile/view.sh memray VIEW=tree ./scripts/profile/view.sh memray # terminal VIEW=stats ./scripts/profile/view.sh memray # terminal summary VIEW=summary ./scripts/profile/view.sh memray # top allocators VIEW=leaks ./scripts/profile/view.sh memray # leak-filtered flamegraph ``` ## Load generation Pair any of the in-process lenses (2, 5) with Locust for realistic traffic: ```bash pytest -m stress tests/stress/ ```