From f4f2ca1509288f6f780af50659693a89949e7e46 Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar Date: Mon, 28 Nov 2022 12:26:46 -0500 Subject: realloc: Return unchanged if request is within usable size If there is enough space in the chunk to satisfy the new size, return the old pointer as is, thus avoiding any locks or reallocations. The only real place this has a benefit is in large chunks that tend to get satisfied with mmap, since there is a large enough spare size (up to a page) for it to matter. For allocations on heap, the extra size is typically barely a few bytes (up to 15) and it's unlikely that it would make much difference in performance. Also added a smoke test to ensure that the old pointer is returned unchanged if the new size to realloc is within usable size of the old pointer. Signed-off-by: Siddhesh Poyarekar Reviewed-by: DJ Delorie --- malloc/tst-realloc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'malloc/tst-realloc.c') diff --git a/malloc/tst-realloc.c b/malloc/tst-realloc.c index 5eb62a7..3b78a24 100644 --- a/malloc/tst-realloc.c +++ b/malloc/tst-realloc.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -142,6 +143,28 @@ do_test (void) free (p); + /* Smoke test to make sure that allocations do not move if they have enough + space to expand in the chunk. */ + for (size_t sz = 3; sz < 256 * 1024; sz += 2048) + { + p = realloc (NULL, sz); + if (p == NULL) + FAIL_EXIT1 ("realloc (NULL, %zu) returned NULL.", sz); + size_t newsz = malloc_usable_size (p); + printf ("size: %zu, usable size: %zu, extra: %zu\n", + sz, newsz, newsz - sz); + uintptr_t oldp = (uintptr_t) p; + void *new_p = realloc (p, newsz); + if ((uintptr_t) new_p != oldp) + FAIL_EXIT1 ("Expanding (%zu bytes) to usable size (%zu) moved block", + sz, newsz); + free (new_p); + + /* We encountered a large enough extra size at least once. */ + if (newsz - sz > 1024) + break; + } + return 0; } -- cgit v1.1