Summary
py-spy 0.4.1 is immediately OOM-killed when attaching to a Python process on a Raspberry Pi Zero 2 W (418 MB total RAM, no swap). Even a single py-spy dump command (one-shot, no recording) consumes ~188 MB RSS before producing any output, leaving no room on a system with ~190 MB available.
Reproduction
Environment
- Device: Raspberry Pi Zero 2 W Rev 1.0
- Kernel:
Linux 6.1.61-v8 #1 SMP PREEMPT aarch64
- RAM: 418 MB total, ~190 MB available, 0 swap
- Python: 3.10.8
- py-spy: 0.4.1 (
py_spy-0.4.1-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl, stripped to 4 MB)
- Target process: nbdkit with Python plugin (19 threads, 122 MB RSS, 195 memory map entries / 17 KB maps file)
Target process memory profile
VmPeak: 1648952 kB
VmSize: 1648952 kB
VmRSS: 122164 kB
VmData: 468536 kB
VmStk: 132 kB
VmExe: 120 kB
VmLib: 5504 kB
Threads: 19
The large VmSize (1.6 GB) is due to a memory-mapped virtual disk (cow overlay), but physical RSS is only 122 MB. The /proc/PID/maps file is 195 lines / 17 KB — entirely unremarkable.
Steps to reproduce
# System has ~190 MB available
$ free -m
total used free shared buff/cache available
Mem: 418 206 150 8 62 184
# Even dropping caches first doesn't help
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
# All three commands below are OOM-killed:
# 1. Record (30s, low rate, raw format, nonblocking)
$ sudo py-spy record -d 10 -r 10 -f raw -o /tmp/profile.txt --pid $PID --nonblocking
Killed
# 2. Record (30s, speedscope format, nonblocking)
$ sudo py-spy record -d 30 -f speedscope -o /tmp/profile.json --pid $PID --nonblocking
Killed
# 3. Even a single one-shot dump
$ sudo py-spy dump --pid $PID --nonblocking
Killed
OOM killer logs
All three invocations show consistent ~188 MB RSS at time of kill:
[13249.172217] py-spy invoked oom-killer: gfp_mask=0x140dca(GFP_HIGHUSER_MOVABLE|__GFP_COMP|__GFP_ZERO), order=0, oom_score_adj=0
[13249.854438] [ 46539] 0 46539 50783 47891 421888 0 0 py-spy
[13249.879179] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=py-spy,pid=46539,uid=0
[13249.896146] Out of memory: Killed process 46539 (py-spy) total-vm:203132kB, anon-rss:188684kB, file-rss:0kB, shmem-rss:2880kB, UID:0
[13347.396689] oom-kill: [...] task=py-spy,pid=46910 [...]
[13347.413705] Out of memory: Killed process 46910 (py-spy) total-vm:203132kB, anon-rss:188056kB, file-rss:0kB, shmem-rss:1152kB, UID:0
[13370.378316] oom-kill: [...] task=py-spy,pid=46996 [...]
Analysis
- py-spy's total-vm is 203 MB and anon-rss is 188 MB — this is consistent across all 3 invocations, suggesting it's a fixed startup cost rather than unbounded growth.
- The target process has only 195 memory map entries (17 KB maps file) and 122 MB RSS — this is a small, well-behaved process.
- 188 MB for a profiler is untenable on embedded/IoT devices. For reference, the Raspberry Pi Zero 2 W (512 MB model, ~418 MB available to userspace) is a popular target for Python applications, and the PS3 shipped with 256 MB total.
- The
--nonblocking flag was used across all invocations.
py-spy dump (a single snapshot, no recording) also fails, so this is not about sample buffer accumulation — the cost is at startup.
Expected behavior
py-spy should be usable on devices with 512 MB RAM. A single py-spy dump against a small Python process should not require ~188 MB RSS to produce a one-shot stack trace.
Summary
py-spy 0.4.1 is immediately OOM-killed when attaching to a Python process on a Raspberry Pi Zero 2 W (418 MB total RAM, no swap). Even a single
py-spy dumpcommand (one-shot, no recording) consumes ~188 MB RSS before producing any output, leaving no room on a system with ~190 MB available.Reproduction
Environment
Linux 6.1.61-v8 #1 SMP PREEMPT aarch64py_spy-0.4.1-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl, stripped to 4 MB)Target process memory profile
The large VmSize (1.6 GB) is due to a memory-mapped virtual disk (cow overlay), but physical RSS is only 122 MB. The
/proc/PID/mapsfile is 195 lines / 17 KB — entirely unremarkable.Steps to reproduce
OOM killer logs
All three invocations show consistent ~188 MB RSS at time of kill:
Analysis
--nonblockingflag was used across all invocations.py-spy dump(a single snapshot, no recording) also fails, so this is not about sample buffer accumulation — the cost is at startup.Expected behavior
py-spy should be usable on devices with 512 MB RAM. A single
py-spy dumpagainst a small Python process should not require ~188 MB RSS to produce a one-shot stack trace.