Skip to content

Commit

Permalink
mrs_realloc: avoid copies when space is available
Browse files Browse the repository at this point in the history
When the passed pointer is valid and already has enough space, return it
unless it's at least twice the requested size.

Some software uses realloc to extend allocations by small, fixed
amounts.  In a naive implementation of realloc that blindly performs
a new allocation, copies the data, and then frees the old allocation,
this is O(n^2).  For small values of `n` this isn't too noticable, but
asymptotically it's quite bad and revocation makes it much worse.
With current tuning, we eventually reach a point where approximately
every 4th allocation triggers a revocation pass.

We can make this somewhat less visible (or fix it entirely for snmalloc
with it's power-of-two sized buckets) by omitting unnecessary
allocations and copies.

Bias towards improving linear increase performance over space saving
and only reallocate to shrink the allocation if we'd save at least 50%
space.  If we chose a smaller value then we end up doing full reallocs
constantly with an allocator like snmalloc.
  • Loading branch information
brooksdavis committed Jul 2, 2024
1 parent bdeff30 commit b2b15d5
Showing 1 changed file with 13 additions and 0 deletions.
13 changes: 13 additions & 0 deletions lib/libc/stdlib/malloc/mrs/mrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1515,6 +1515,19 @@ mrs_realloc(void *ptr, size_t size)
mrs_debug_printf("mrs_realloc: called ptr %p ptr size %zu new size %zu\n",
ptr, old_size, size);

/*
* Just return the pointer if our desired size fits.
*
* Only try to reclaim space by copying if we'd recover at least
* half of the allocated storage. In any other case we can't
* tell the difference between shrinking and linear growth into
* a very large over-allocation (e.g., growing into snmalloc's
* power-of-two buckets by 1K).
*/
if (ptr != NULL && cheri_gettag(ptr) && cheri_getoffset(ptr) == 0 &&
size <= old_size && old_size - size > (old_size >> 1))
return (ptr);

void *new_alloc = mrs_malloc(size);

/*
Expand Down

0 comments on commit b2b15d5

Please sign in to comment.