Skip to content

Measure memory_threshold against the test process's own RSS - #122

Merged
davidanthoff merged 2 commits into
mainfrom
memory-recycle-process-rss
Sep 25, 2026
Merged

davidanthoff merged 2 commits into
mainfrom
memory-recycle-process-rss

Conversation

@davidanthoff

Copy link
Copy Markdown
Member

Summary

memory_threshold, an experimental option that is off by default, now compares the test process's own current resident memory with total system memory. It used to look at system-wide memory use. A test process recycles itself once rss / Sys.total_memory() > threshold.

Why

The old check was 1 - Sys.free_memory()/Sys.total_memory() > threshold. On macOS, Sys.free_memory() stays close to zero even on an idle machine: on GitHub's macOS arm64 runners we measured 0.07–0.19 GB free out of 7 GB. So any threshold fired after every item, and every item paid for a process restart. A system-wide figure also recycles one process because of memory that other processes are using.

Recycling is the only mechanism that gives back memory a test process still holds live. Compiled code and caches grow over a process's lifetime, and no GC can free them. Measuring per process makes the option usable on every platform.

Changes

  • New testprocess/TestItemServer/src/process_memory.jl with _current_rss(): current resident memory, not the peak that Sys.maxrss() reports.
    • Linux: /proc/self/statm.
    • macOS: task_info(MACH_TASK_BASIC_INFO). The struct layout was checked against the xnu headers.
    • Windows: K32GetProcessMemoryInfo with stdcall. SIZE_T is declared as Csize_t, so the struct is also correct in 32-bit Julia.
    • It uses only plain ccall and Julia 1.0-era Base, because the test server runs on Julia 1.0 and later. It returns nothing (never recycle) when it can't measure.
  • _memory_over_threshold uses it. A threshold of 0.0 still recycles after every item, as the existing tests expect.
  • The option is documented in the protocol, TestRunState, the test server and the execute_testrun docstring.
  • New tests: _current_rss returns a plausible value, and a threshold of 1.0 never recycles.
  • CHANGELOG entry. The option is experimental, so the change of meaning is noted rather than treated as breaking.

Testing

  • test/test_worker_lifecycle.jl: 61/61 pass on Julia 1.12.7 (Windows). The "Julia 1.0/1.6 platform" items also pass, so the test server still loads there.
  • _current_rss() checked directly on Windows with Julia 1.0.5, 1.6.7, 1.12.7 and 1.13.0:
    • It agrees with PowerShell's WorkingSet64 to within 0.6 MB.
    • It follows an allocation up, then back down after GC.gc(), while Sys.maxrss() stays at the peak.
  • Only CI will exercise these paths: Linux, macOS and 32-bit Windows. The new _current_rss test item covers them.

Related

Follow-up to the arm64 GC investigation, alongside #121 (GC between items opt-in).

🤖 Generated with Claude Code

The memory recycle check compared whole-system memory use,
1 - Sys.free_memory()/Sys.total_memory(), against the threshold. On macOS
free memory stays near zero even on an idle machine (0.07-0.19 GB of 7 GB
on GitHub arm64 runners), so any threshold recycled the test process after
every item, and a process was also blamed for memory other processes used.

The threshold is now the fraction of total system memory that one test
process's current resident memory may reach. `_current_rss()` reads it
from /proc/self/statm on Linux, task_info(MACH_TASK_BASIC_INFO) on macOS
and K32GetProcessMemoryInfo on Windows, using plain ccall so it works on
every Julia version the test server supports (1.0 on). When the RSS cannot
be determined the check never fires. A threshold of 0.0 still recycles
after every item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@davidanthoff
davidanthoff merged commit 60bfd8f into main Sep 25, 2026
6 checks passed
@davidanthoff
davidanthoff deleted the memory-recycle-process-rss branch September 25, 2026 15:17
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