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 mrs tuning, we eventually reach a point where approximately
every 4th increment 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.
  • Loading branch information
brooksdavis committed Jul 24, 2024
1 parent 37b599d commit 028410e
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 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,21 @@ 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);

/*
* If the new size fits in the current allocation and we won't
* be wasting too much space, just return the existing pointer.
*
* Only try to reclaim space by copying if we'd recover at least
* half of the allocated storage. In other cases we can't tell
* the difference between shrinking and linear growth into a
* large over-allocation (e.g., growing into snmalloc's
* power-of-two buckets by 1K) and we especially want to avoid
* copying such cases.
*/
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 028410e

Please sign in to comment.