From be3417e947a1f17e5fa4137481668779be532bc5 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Sun, 26 Oct 2025 21:14:44 +0100 Subject: [PATCH 1/3] a: use huge allocations --- src/backend/access/gin/gininsert.c | 81 +++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index 3d71b442aa9..085c85718cc 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -198,6 +198,10 @@ static GinTuple *_gin_build_tuple(OffsetNumber attrnum, unsigned char category, ItemPointerData *items, uint32 nitems, Size *len); +static ItemPointer mergeItemPointers(ItemPointerData *a, uint32 na, + ItemPointerData *b, uint32 nb, + int *nmerged); + /* * Adds array of item pointers to tuple's posting list, or * creates posting tree and tuple pointing to tree in case @@ -1496,14 +1500,15 @@ GinBufferStoreTuple(GinBuffer *buffer, GinTuple *tup) * still pass 0 as number of elements in that array though. */ if (buffer->items == NULL) - buffer->items = palloc((buffer->nitems + tup->nitems) * sizeof(ItemPointerData)); + buffer->items = MemoryContextAllocHuge(CurrentMemoryContext, + (buffer->nitems + tup->nitems) * sizeof(ItemPointerData)); else - buffer->items = repalloc(buffer->items, - (buffer->nitems + tup->nitems) * sizeof(ItemPointerData)); + buffer->items = repalloc_huge(buffer->items, + (buffer->nitems + tup->nitems) * sizeof(ItemPointerData)); - new = ginMergeItemPointers(&buffer->items[buffer->nfrozen], /* first unfrozen */ - (buffer->nitems - buffer->nfrozen), /* num of unfrozen */ - items, tup->nitems, &nnew); + new = mergeItemPointers(&buffer->items[buffer->nfrozen], /* first unfrozen */ + (buffer->nitems - buffer->nfrozen), /* num of unfrozen */ + items, tup->nitems, &nnew); Assert(nnew == (tup->nitems + (buffer->nitems - buffer->nfrozen))); @@ -2441,3 +2446,67 @@ _gin_compare_tuples(GinTuple *a, GinTuple *b, SortSupport ssup) return ItemPointerCompare(GinTupleGetFirst(a), GinTupleGetFirst(b)); } + + +/* + * local copy, doing palloc_huge + */ +static ItemPointer +mergeItemPointers(ItemPointerData *a, uint32 na, + ItemPointerData *b, uint32 nb, + int *nmerged) +{ + ItemPointerData *dst; + + dst = (ItemPointer) MemoryContextAllocHuge(CurrentMemoryContext, + (na + nb) * sizeof(ItemPointerData)); + + /* + * If the argument arrays don't overlap, we can just append them to each + * other. + */ + if (na == 0 || nb == 0 || ginCompareItemPointers(&a[na - 1], &b[0]) < 0) + { + memcpy(dst, a, na * sizeof(ItemPointerData)); + memcpy(&dst[na], b, nb * sizeof(ItemPointerData)); + *nmerged = na + nb; + } + else if (ginCompareItemPointers(&b[nb - 1], &a[0]) < 0) + { + memcpy(dst, b, nb * sizeof(ItemPointerData)); + memcpy(&dst[nb], a, na * sizeof(ItemPointerData)); + *nmerged = na + nb; + } + else + { + ItemPointerData *dptr = dst; + ItemPointerData *aptr = a; + ItemPointerData *bptr = b; + + while (aptr - a < na && bptr - b < nb) + { + int cmp = ginCompareItemPointers(aptr, bptr); + + if (cmp > 0) + *dptr++ = *bptr++; + else if (cmp == 0) + { + /* only keep one copy of the identical items */ + *dptr++ = *bptr++; + aptr++; + } + else + *dptr++ = *aptr++; + } + + while (aptr - a < na) + *dptr++ = *aptr++; + + while (bptr - b < nb) + *dptr++ = *bptr++; + + *nmerged = dptr - dst; + } + + return dst; +} -- 2.51.0