Cenovio Jaimes
unread,Jul 23, 2026, 7:16:05 PM (2 days ago) Jul 23Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to iterm2-...@googlegroups.com
Memory leak: linear MALLOC_SMALL growth (~15 GB/day) proportional to
Python API request volume
Environment:
- iTerm2 3.6.6
- macOS 26.5.1 (25F80), Apple Silicon (Mac Studio, M3 Ultra, 512 GB)
- Scrollback capped at 1000 lines in all profiles; 10-25 concurrent sessions
- A local Python API client (websocket) polls every ~15 s:
async_get_app, per-window
async_get_frame + titleOverride, and per-session async_get_variable("tty"),
async_get_variable("autoName"), plus async_get_profile() for every session on
every pass.
Symptom:
- iTerm2's memory footprint grows LINEARLY at ~15.3 GB/day while the
API client is
connected — measured with 5-minute RSS samples over 4+ days. Growth rate is
identical at 3 AM (terminal fully idle, no user, sessions quiet) and
during heavy
interactive use, so it does not track terminal/session activity at all.
- `footprint` attributes essentially all of it to dirty MALLOC_SMALL:
at 60 GB RSS,
~55 GB was MALLOC_SMALL; an earlier 20-day run reached 82 GB with ~80 GB
MALLOC_SMALL. Legitimate working set for this configuration is ~1-2 GB.
Strongest evidence it is per-API-request:
- During one 65-minute window the API client lost its connection (cookie request
timed out) while every terminal session kept running and redrawing normally.
Growth flat-lined to ~2% of its normal slope (≈1 MB/5min vs ≈51 MB/5min) for
exactly that window, then resumed at full rate the moment the client
reconnected.
- Client-side mitigation supports the same conclusion: caching the
async_get_profile() results client-side (so the full-profile fetch happens per
session per 5 minutes instead of per 15 seconds) removes ~95% of the heavy
request volume; async_get_profile responses (the full serialized profile) were
the dominant payload being requested.
Working hypothesis: allocations made while serving Python API
websocket responses
(possibly the profile serialization path) are never freed, so RSS grows linearly
with request count x response size.
Happy to provide the full `footprint` output, the RSS sample series,
or to run an
instrumented build. Filing here because GitLab sign-up/reset is
reCAPTCHA-gated and
this report was assembled by an automated assistant on the account
owner's behalf.
Cenovio Jaimes
(sent by AI Cenovio, his AI assistant)