Skip to content

Signal memory pressure relief and expose PSI readings - #5

Merged
carlhoerberg merged 4 commits into
mainfrom
memory-pressure-relief
Oct 1, 2026
Merged

carlhoerberg merged 4 commits into
mainfrom
memory-pressure-relief

Conversation

@carlhoerberg

@carlhoerberg carlhoerberg commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Why

systemd's memory pressure notifications only signal the onset of pressure. An application that backs off under pressure (blocks publishing, refuses connections) has no way to know when to resume. LavinMQ needs this for cloudamqp/lavinmq#2307.

What

Relief signalling: a new watch method calls its block with a Bool, true when pressure is detected and false when it's relieved:

SystemD::MemoryPressure.watch(release_below: 1.0, check_interval: 1.second) do |pressure|
  pressure ? pause_work : resume_work
end

It's a separate method instead of an argument to monitor, because Crystal lets a block ignore its arguments, so the compiler couldn't flag existing monitor { ... } callers that would suddenly also be called on relief.

While under pressure, watch polls the PSI file every check_interval instead of blocking forever. It signals relief once some avg10 drops below release_below (percent), or at the first check if no PSI file can be read.

PSI readings

  • MemoryPressure.pressure returns the current Pressure (some/full Stalls with avg10/avg60/avg300/total). It reads the watched file when that's a .pressure file, otherwise the process' cgroup v2 memory.pressure, falling back to /proc/pressure/memory.
  • MemoryPressure.parse(data) parses PSI file contents.

Refactor: the separate FIFO, Unix-socket and regular-file loops are merged into one Watcher, with the same per-kind behaviour (POLLPRI for regular files, read-and-discard for FIFOs and sockets, reconnect on socket EOF).

Compatibility

monitor { ... } is unchanged: it's called on pressure only and never polls. The existing monitor specs pass without modification.

Testing

New specs cover PSI parsing, reading from a file, path selection, watch signalling relief, watch not signalling relief while pressure persists, and monitor only being called on pressure. crystal spec -Dpreview_mt -Dexecution_context: 21 examples, 0 failures.

🤖 Generated with Claude Code

https://claude.ai/code/session_011ob4Nr8aeNr1kj3PgMosUS

Pressure notifications only signal the onset. The monitor block now
takes a Bool: true when pressure is detected, false when it's relieved.
While under pressure the PSI file is polled every check_interval and
relief is signalled once "some avg10" drops below release_below.

Adds MemoryPressure.pressure to read the current PSI (watched
.pressure file, the cgroup's memory.pressure, or /proc/pressure/memory)
and MemoryPressure.parse for PSI data.

The FIFO, socket and regular file watch loops are merged into one
Watcher.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011ob4Nr8aeNr1kj3PgMosUS
@carlhoerberg
carlhoerberg requested a review from a team as a code owner October 1, 2026 17:06
carlhoerberg and others added 2 commits October 1, 2026 20:01
@carlhoerberg
carlhoerberg merged commit 2b28d84 into main Oct 1, 2026
4 checks passed
@carlhoerberg
carlhoerberg deleted the memory-pressure-relief branch October 1, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant