memtuples_POCWIP.patch
application/octet-stream
Filename: memtuples_POCWIP.patch
Type: application/octet-stream
Part: 0
Message:
Re: Memory usage during sorting
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
| File | + | − |
|---|---|---|
| src/backend/utils/mmgr/mcxt.c | 32 | 0 |
| src/backend/utils/sort/tuplesort.c | 5 | 6 |
| src/include/utils/palloc.h | 1 | 0 |
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 466d53d..4d4f9ec 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -695,6 +695,38 @@ repalloc(void *pointer, Size size)
pointer, size);
}
+/* repallocJJ -- like repalloc only lets you exceed MaxAllocSize
+ * By using this function, you solemnly plege that you will not
+ * pass the returned pointer to aset.c code or varlena objects.
+ * see src/include/utils/memutils.h MaxAllocSize comments.
+void *
+repallocJJ(void *pointer, Size size)
+{
+ StandardChunkHeader *header;
+
+ /*
+ * Try to detect bogus pointers handed to us, poorly though we can.
+ * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
+ * allocated chunk.
+ */
+ Assert(pointer != NULL);
+ Assert(pointer == (void *) MAXALIGN(pointer));
+
+ /*
+ * OK, it's probably safe to look at the chunk header.
+ */
+ header = (StandardChunkHeader *)
+ ((char *) pointer - STANDARDCHUNKHEADERSIZE);
+
+ AssertArg(MemoryContextIsValid(header->context));
+
+ /* isReset must be false already */
+ Assert(!header->context->isReset);
+
+ return (*header->context->methods->realloc) (header->context,
+ pointer, size);
+}
+
/*
* MemoryContextSwitchTo
* Returns the current context; installs the given context.
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 1452e8c..8d28548 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -960,14 +960,13 @@ grow_memtuples(Tuplesortstate *state)
/*
* On a 64-bit machine, allowedMem could be high enough to get us into
* trouble with MaxAllocSize, too.
+ * Get around this by using our own repalloc version
*/
- if ((Size) (state->memtupsize * 2) >= MaxAllocSize / sizeof(SortTuple))
- return false;
FREEMEM(state, GetMemoryChunkSpace(state->memtuples));
state->memtupsize *= 2;
state->memtuples = (SortTuple *)
- repalloc(state->memtuples,
+ repallocJJ(state->memtuples,
state->memtupsize * sizeof(SortTuple));
USEMEM(state, GetMemoryChunkSpace(state->memtuples));
if (LACKMEM(state))
@@ -1653,9 +1652,9 @@ inittapes(Tuplesortstate *state)
state->tapeRange = maxTapes - 1;
#ifdef TRACE_SORT
- if (trace_sort)
- elog(LOG, "switching to external sort with %d tapes: %s",
- maxTapes, pg_rusage_show(&state->ru_start));
+ if (trace_sort)
+ elog(LOG, "switching to external sort at %d/%d tuples with %d tapes: %s",
+ state->memtupcount, state->memtupsize, maxTapes, pg_rusage_show(&state->ru_start));
#endif
/*
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index 973f306..50cc864 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -69,6 +69,7 @@ extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
extern void pfree(void *pointer);
extern void *repalloc(void *pointer, Size size);
+extern void *repallocJJ(void *pointer, Size size);
/*
* MemoryContextSwitchTo can't be a macro in standard C compilers.