sortmem_grow-v1.patch
application/octet-stream
Filename: sortmem_grow-v1.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/utils/sort/tuplesort.c | 0 | 0 |
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
new file mode 100644
index 1452e8c..9c5d85a
*** a/src/backend/utils/sort/tuplesort.c
--- b/src/backend/utils/sort/tuplesort.c
*************** struct Tuplesortstate
*** 273,278 ****
--- 273,280 ----
SortTuple *memtuples; /* array of SortTuple structs */
int memtupcount; /* number of tuples currently present */
int memtupsize; /* allocated length of memtuples array */
+ bool final_memtupsize; /* true if we are no longer growing memtupsize */
+
/*
* While building initial runs, this is the current output run number
*************** tuplesort_begin_common(int workMem, bool
*** 546,551 ****
--- 548,554 ----
state->randomAccess = randomAccess;
state->bounded = false;
state->boundUsed = false;
+ state->final_memtupsize = false;
state->allowedMem = workMem * 1024L;
state->availMem = state->allowedMem;
state->sortcontext = sortcontext;
*************** tuplesort_end(Tuplesortstate *state)
*** 937,950 ****
* Grow the memtuples[] array, if possible within our memory constraint.
* Return TRUE if able to enlarge the array, FALSE if not.
*
! * At each increment we double the size of the array. When we are short
* on memory we could consider smaller increases, but because availMem
! * moves around with tuple addition/removal, this might result in thrashing.
* Small increases in the array size are likely to be pretty inefficient.
*/
static bool
grow_memtuples(Tuplesortstate *state)
{
/*
* We need to be sure that we do not cause LACKMEM to become true, else
* the space management algorithm will go nuts. We assume here that the
--- 940,957 ----
* Grow the memtuples[] array, if possible within our memory constraint.
* Return TRUE if able to enlarge the array, FALSE if not.
*
! * At each increment except possibly the last one we double the size of
! * the array. When we are short
* on memory we could consider smaller increases, but because availMem
! * moves around with tuple addition/removal, this might result in thrashing,
! * so only allow it to happen once.
* Small increases in the array size are likely to be pretty inefficient.
*/
static bool
grow_memtuples(Tuplesortstate *state)
{
+ int new_memtupsize;
+
/*
* We need to be sure that we do not cause LACKMEM to become true, else
* the space management algorithm will go nuts. We assume here that the
*************** grow_memtuples(Tuplesortstate *state)
*** 953,971 ****
* minimum array size established in tuplesort_begin_common is large
* enough to force palloc to treat it as a separate chunk, so this
* assumption should be good. But let's check it.)
*/
! if (state->availMem <= (long) (state->memtupsize * sizeof(SortTuple)))
return false;
/*
* On a 64-bit machine, allowedMem could be high enough to get us into
* trouble with MaxAllocSize, too.
*/
! if ((Size) (state->memtupsize * 2) >= MaxAllocSize / sizeof(SortTuple))
return false;
FREEMEM(state, GetMemoryChunkSpace(state->memtuples));
! state->memtupsize *= 2;
state->memtuples = (SortTuple *)
repalloc(state->memtuples,
state->memtupsize * sizeof(SortTuple));
--- 960,994 ----
* minimum array size established in tuplesort_begin_common is large
* enough to force palloc to treat it as a separate chunk, so this
* assumption should be good. But let's check it.)
+ * XXXX is the new method still follow this? The last allocation is no
+ * longer necessarily a power of 2, but that is not freed.
+ *
+ * Once we are approaching the final growth of memtuples, use the
+ * historical size of the tuples seen so far try to estimate the
+ * best final growth size to make most efficient use of memory.
*/
! if (state->final_memtupsize)
return false;
+ if (state->availMem < state->allowedMem/2)
+ {
+ new_memtupsize = (int) ((float)state->memtupsize * (float) state->allowedMem / (float) (state->allowedMem - state->availMem));
+ state->final_memtupsize = true;
+ }
+ else
+ {
+ new_memtupsize = state->memtupsize * 2;
+ };
+
/*
* On a 64-bit machine, allowedMem could be high enough to get us into
* trouble with MaxAllocSize, too.
*/
! if ((Size) (new_memtupsize) >= MaxAllocSize / sizeof(SortTuple))
return false;
FREEMEM(state, GetMemoryChunkSpace(state->memtuples));
! state->memtupsize = new_memtupsize;
state->memtuples = (SortTuple *)
repalloc(state->memtuples,
state->memtupsize * sizeof(SortTuple));