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 performes
a new allocation, copies the data, and the frees the old allocation,
this is O(n^2).  For small values of `n` this isn't too noticable, but
for asymptotically it's quite bad and revocation makes it much worse.
With current tuning, we eventually reach a point where approximately
every 4th allocating triggers a revocation pass.

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

Bias towards improveing 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 1, 2024
1 parent bdeff30 commit f0ab240
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 f0ab240

Please sign in to comment.