Memory: hand freed memory back after bursts #314

Closed
kayg wants to merge 1 commit from issue/44-trim-3 into dev
Owner

Part of #44. Replaces #248 (rebased onto dev, and now also trims after the last request and when a room closes). Independent of #227 and the search PRs.

glibc keeps what a burst freed (startup scan, list store catching up, a search build or catch-up, big answers) in its per-thread heaps and rarely returns it: on the perf VM at 100k notes, dev sits at 284-385 MB RSS at rest with ~30-40 MB live (heaptrack).

  • New small crate calternal-memory: after_burst() calls glibc's malloc_trim(0) once things have been quiet for 2 s after the last burst. A burst arms one wait on a thread of its own: no timers, no wake-ups at rest (the idle.wakeups_per_s gate stays at 0).
  • Hooked after: the startup scan, big list refreshes (>= 512 notes), search catch-up and updates, every HTTP request (a response layer, cheap: one atomic store), and a room closing (it frees the note's document).
  • Needs a nod: it is the one crate allowed an unsafe call, for that one call ([lints.rust] unsafe_code = "deny" plus an allow on it). The workspace still forbids unsafe everywhere else.

Numbers: see #44 (perf VM, 1k/10k/100k).

🤖 Generated with Claude Code

Part of #44. Replaces #248 (rebased onto dev, and now also trims after the last request and when a room closes). Independent of #227 and the search PRs. glibc keeps what a burst freed (startup scan, list store catching up, a search build or catch-up, big answers) in its per-thread heaps and rarely returns it: on the perf VM at 100k notes, dev sits at 284-385 MB RSS at rest with ~30-40 MB live (heaptrack). - New small crate `calternal-memory`: `after_burst()` calls glibc's `malloc_trim(0)` once things have been quiet for 2 s after the last burst. A burst arms one wait on a thread of its own: no timers, no wake-ups at rest (the `idle.wakeups_per_s` gate stays at 0). - Hooked after: the startup scan, big list refreshes (>= 512 notes), search catch-up and updates, every HTTP request (a response layer, cheap: one atomic store), and a room closing (it frees the note's document). - **Needs a nod:** it is the one crate allowed an `unsafe` call, for that one call (`[lints.rust] unsafe_code = "deny"` plus an `allow` on it). The workspace still forbids `unsafe` everywhere else. Numbers: see #44 (perf VM, 1k/10k/100k). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Memory: hand freed memory back after bursts
Some checks failed
CI / server (pull_request) Successful in 25s
CI / rust (pull_request) Successful in 2m18s
CI / web (pull_request) Failing after 3m3s
fdbaeee3f3
glibc keeps what a burst of work freed (the startup scan, the list store
catching up, a search index build or catch-up, the whole-Home list)
inside its heaps, a heap per thread, and rarely returns it: at 100,000
notes the server sat at 150 MB or more with about 30 MB in use (#44).

A new small crate, `calternal-memory`, calls glibc's `malloc_trim` two
seconds after the last burst (a burst arms one wait on a thread of its
own: nothing runs on a timer, an idle server never wakes up for it). It
is the one crate allowed an `unsafe` call, for that one call; the
workspace still forbids `unsafe` everywhere else. Hooked after the
startup scan, big list refreshes, search catch-up and updates, and the
whole-Home list.

Local, 100k notes, system allocator: settled 82 -> 60 MB, after searches
152-160 -> 84 MB.

Part of #44

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Author
Owner

Superseded by #427 (#398): the same commit, rebased onto #417, which removes the whole-Home notes.list and with it this PR's after_burst call there. On the perf VM at 100k, glibc with two heaps (#418), trim and no THP stayed ahead of mimalloc v2/v3 and jemalloc (table on #427). Closing in favour of #427.

Superseded by #427 (#398): the same commit, rebased onto #417, which removes the whole-Home `notes.list` and with it this PR's `after_burst` call there. On the perf VM at 100k, glibc with two heaps (#418), trim and no THP stayed ahead of mimalloc v2/v3 and jemalloc (table on #427). Closing in favour of #427.
kayg closed this pull request 2026-10-15 10:02:24 +00:00
Some checks failed
CI / server (pull_request) Successful in 25s
CI / rust (pull_request) Successful in 2m18s
CI / web (pull_request) Failing after 3m3s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!314
No description provided.