Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/foundation/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,17 @@ size_t cbm_mem_rss(void) {
size_t cbm_mem_peak_rss(void) {
size_t peak_rss = 0;
mi_process_info(NULL, NULL, NULL, NULL, &peak_rss, NULL, NULL, NULL);
/* Peak RSS is by definition >= current RSS. On Linux cbm_mem_rss() reads the
* live /proc/self/statm value (page-granular), while mimalloc's peak_rss
* comes from getrusage's ru_maxrss (KB-granular, and it can lag the live
* statm read by a few pages). Reading the two sources independently lets a
* fresh current read momentarily exceed the reported peak, breaking the
* peak >= current invariant. Reconcile them: the true peak is at least the
* current RSS. (Not observable on macOS, where both come from mimalloc.) */
size_t current = cbm_mem_rss();
if (current > peak_rss) {
peak_rss = current;
}
if (peak_rss > 0) {
return peak_rss;
}
Expand Down
15 changes: 14 additions & 1 deletion tests/test_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,23 @@ TEST(mem_rss_positive) {

TEST(mem_peak_rss_gte_rss) {
cbm_mem_init(0.5);
/* peak >= current RSS is definitional. Regression guard for the Linux
* statm-vs-ru_maxrss source mismatch: cbm_mem_rss() reads the live
* /proc/self/statm value (page-granular) while mimalloc's peak comes from
* getrusage ru_maxrss (KB-granular, and it lags), so a live current read
* could momentarily exceed the reported peak by a few pages and break the
* invariant. cbm_mem_peak_rss() now reconciles the two sources. Touch a
* fresh buffer so the check runs against a non-trivial live current read.
* (Linux-only bug — macOS reads both from mimalloc; it flaked on the
* Linux/ARM CI leg, which is the authoritative reproduction tier.) */
size_t n = 32 * 1024 * 1024;
char *p = (char *)malloc(n);
ASSERT_NOT_NULL(p);
memset(p, 0xBE, n); /* fault in all pages so current RSS is non-trivial */
size_t rss = cbm_mem_rss();
size_t peak = cbm_mem_peak_rss();
/* Peak must be >= current RSS */
ASSERT_GTE(peak, rss);
free(p);
PASS();
}

Expand Down
Loading