ReMem
A lightweight memory recycler and garbage collector for C, built for predictable performance without a runtime.
- page lookups
- O(1)
- overhead vs malloc/free
- 1.39×
- faster than Python (low-end HW)
- 8–9×
- dependencies
- 0
Overview
ReMem started as an experiment to see how far you can push higher-level memory conveniences without leaving C. Writing hobby kernels, interpreters, and ML primitives made it clear how much time gets sunk into manual allocation hygiene. ReMem is a tool that feels safe enough for prototypes yet light enough for systems projects — no runtime required.
Design Goals
- Compatibility first. No external dependencies. Works on Linux, macOS, Apple Silicon, and older x86 hardware without modification.
- Predictable performance. Allocations route through size-classed arenas and resolve in O(1). Freed pages are recycled rather than returning to the OS on every free.
- Drop-in ergonomics. The API mirrors
malloc/free, so existing projects can adopt it incrementally with optional hooks for rooting GC-managed pointers.
How It Works
ReMem groups allocations into size classes, storing them inside arena-backed pages. When a block is freed, the collector marks it for reuse. Pages that drain completely are either cached in-memory or returned to the underlying arena depending on the freeMemory toggle. Page lookups — and the mapping from blocks back to their parent arenas — stay O(1) via dense indexing tables.
Large allocations that don't fit within a standard page are shunted directly to the underlying arena and live until the GC is destroyed, keeping the hot path simple while covering edge cases.
API
int main(void) {
int stack_top;
// false = cache empty pages (faster); true = return to OS (lower RSS)
if (!gcInit(&stack_top, false)) return 1;
int *buffer = gcAlloc(sizeof(int) * 1024);
buffer[0] = 42;
gcCollect(); // manual collection trigger
gcDestroy(); // free everything
return 0;
}
Performance
Benchmarked on an Apple M3 Pro and a low-power Intel N150 with a 16 GB workload. ReMem carries a ~1.39× constant overhead vs raw malloc/free on the M3 Pro — well within acceptable range for the safety and ergonomics it provides, and dramatically ahead of Python-level runtimes.
malloc/free: ~2s (M3 Pro) / ~4s (Intel N150)- ReMem, pages cached: ~3s / ~19s — 0.95× RSS vs baseline
- ReMem, pages freed: ~3s / ~40s — 0.94× RSS
- Python reference: ~38s / ~81s
Disabling page freeing (freeMemory = false) keeps the hot path fast at the cost of slightly higher RSS. On the M3 Pro, RSS actually ends up lower than a bare arena-only approach due to page recycling.
Roadmap
- Nursery — projected 1.5–5× speedup for short-lived allocation patterns
- Multithreading — per-thread arenas, lock-free hot path
- Instrumentation — real-time stats via
gcDebugPrintStats()improvements