util: Avoid waste space when linear alloc'ing large sizes

In the linear allocator, when a size larger than the minimum
buffer size is allocated, we currently create the new buffer
to fit exactly the requested size.

In that case, don't bother updating the `latest` pointer, since
this newly created buffer is already full.  In the worst case,
the current `latest` is full and it would be the same; in the
best case, there's still room for small allocations, so we avoid
wasting space if the next allocations would fit.

Reviewed-by: Emma Anholt <emma@anholt.net>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25517>
This commit is contained in:
Caio Oliveira
2023-10-02 23:24:51 -07:00
committed by Marge Bot
parent 52721cfbe8
commit c005b5a16f
2 changed files with 35 additions and 4 deletions
+18 -4
View File
@@ -1032,14 +1032,28 @@ linear_alloc_child(linear_ctx *ctx, unsigned size)
if (unlikely(!ptr))
return NULL;
ctx->offset = 0;
ctx->size = node_size;
ctx->latest = ptr + canary_size;
#ifndef NDEBUG
linear_node_canary *canary = get_node_canary(ctx->latest);
linear_node_canary *canary = (void *) ptr;
canary->magic = LMAGIC_NODE;
canary->offset = 0;
#endif
/* If the new buffer is going to be full, don't update `latest`
* pointer. Either the current one is also full, so doesn't
* matter, or the current one is not full, so there's still chance
* to use that space.
*/
if (unlikely(size == node_size)) {
#ifndef NDEBUG
canary->offset = size;
#endif
assert((uintptr_t)(ptr + canary_size) % SUBALLOC_ALIGNMENT == 0);
return ptr + canary_size;
}
ctx->offset = 0;
ctx->size = node_size;
ctx->latest = ptr + canary_size;
}
void *ptr = (char *)ctx->latest + ctx->offset;
+17
View File
@@ -53,3 +53,20 @@ TEST(LinearAlloc, RewriteTail)
ralloc_free(ctx);
}
TEST(LinearAlloc, AvoidWasteAfterLargeAlloc)
{
void *ctx = ralloc_context(NULL);
linear_ctx *lin_ctx = linear_context(ctx);
char *first = (char *) linear_alloc_child(lin_ctx, 32);
/* Large allocation that would force a larger buffer. */
linear_alloc_child(lin_ctx, 1024 * 16);
char *second = (char *) linear_alloc_child(lin_ctx, 32);
EXPECT_EQ(second - first, 32);
ralloc_free(ctx);
}