agora inbox for [email protected]
help / color / mirror / Atom feedFrom: Tomas Vondra <[email protected]>
Subject: [PATCH 2/3] Generation: keeper block
Date: Sat, 31 Jul 2021 02:54:36 +0200
---
src/backend/utils/mmgr/generation.c | 61 +++++++++++++++++++++++++----
1 file changed, 54 insertions(+), 7 deletions(-)
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 771a2525ca..6c90416e27 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -65,6 +65,7 @@ typedef struct GenerationContext
Size nextBlockSize; /* next block size to allocate */
GenerationBlock *block; /* current (most recently allocated) block */
+ GenerationBlock *keeper; /* keeper block */
dlist_head blocks; /* list of blocks */
} GenerationContext;
@@ -254,6 +255,7 @@ GenerationContextCreate(MemoryContext parent,
set->maxBlockSize = maxBlockSize;
set->nextBlockSize = initBlockSize;
set->block = NULL;
+ set->keeper = NULL;
dlist_init(&set->blocks);
/* Finally, do the type-independent part of context creation */
@@ -302,6 +304,7 @@ GenerationReset(MemoryContext context)
}
set->block = NULL;
+ set->keeper = NULL;
/* Reset block size allocation sequence, too */
set->nextBlockSize = set->initBlockSize;
@@ -344,7 +347,7 @@ GenerationAlloc(MemoryContext context, Size size)
Size chunk_size = MAXALIGN(size);
Size blockSize;
- blockSize = (set->block) ? set->block->blksize : set->nextBlockSize;
+ blockSize = set->initBlockSize;
/* is it an over-sized chunk? if yes, allocate special block */
if (chunk_size > (blockSize / 8))
@@ -400,6 +403,26 @@ GenerationAlloc(MemoryContext context, Size size)
*/
block = set->block;
+ /*
+ * If we can't use the current block, and we have a keeper block with
+ * enough free space in it, use it as the block.
+ *
+ * XXX We don't want to do this when there's not enough free space
+ * (although the keeper block should be empty, so not sure if checking
+ * the space in the keeper block is necessary).
+ */
+ if (((block == NULL) ||
+ (block->endptr - block->freeptr) < Generation_CHUNKHDRSZ + chunk_size) &&
+ (set->keeper != NULL) &&
+ (set->keeper->endptr - set->keeper->freeptr) < Generation_CHUNKHDRSZ + chunk_size)
+ {
+ block = set->keeper;
+ set->keeper = NULL;
+
+ /* keeper block was not counted as allocated, so add it back */
+ context->mem_allocated += block->blksize;
+ }
+
if ((block == NULL) ||
(block->endptr - block->freeptr) < Generation_CHUNKHDRSZ + chunk_size)
{
@@ -524,16 +547,34 @@ GenerationFree(MemoryContext context, void *pointer)
if (block->nfree < block->nchunks)
return;
+ /* Also make sure the block is not marked as the current block. */
+ if (set->block == block)
+ set->block = NULL;
+
+ /* Keep the block for reuse, if we don't have one already. */
+ if (!set->keeper && block->blksize <= set->maxBlockSize)
+ {
+ /* reset the pointers before we use it as keeper block */
+ block->freeptr = ((char *) block) + Generation_BLOCKHDRSZ;
+ block->endptr = ((char *) block) + block->blksize;
+
+ block->nfree = 0;
+ block->nchunks = 0;
+
+ set->keeper = block;
+
+ /* keeper block is not counted as allocated */
+ context->mem_allocated -= block->blksize;
+
+ return;
+ }
+
/*
* The block is empty, so let's get rid of it. First remove it from the
* list of blocks, then return it to malloc().
*/
dlist_delete(&block->node);
- /* Also make sure the block is not marked as the current block. */
- if (set->block == block)
- set->block = NULL;
-
context->mem_allocated -= block->blksize;
free(block);
}
@@ -770,13 +811,19 @@ GenerationCheck(MemoryContext context)
nchunks;
char *ptr;
- total_allocated += block->blksize;
+ /*
+ * The keeper block in the list of blocks, but we don't consider it
+ * as allocated in memory accounting. So don't include it in the sum.
+ */
+ if (block != gen->keeper)
+ total_allocated += block->blksize;
/*
* nfree > nchunks is surely wrong, and we don't expect to see
* equality either, because such a block should have gotten freed.
*/
- if (block->nfree >= block->nchunks)
+ if ((block->nfree > block->nchunks) &&
+ ((block != gen->keeper) && (block->nfree == block->nchunks)))
elog(WARNING, "problem in Generation %s: number of free chunks %d in block %p exceeds %d allocated",
name, block->nfree, block, block->nchunks);
--
2.31.1
--------------132BD247D801061DA85680D7
Content-Type: text/x-patch; charset=UTF-8;
name="0003-Generation-allocChunkLimit.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0003-Generation-allocChunkLimit.patch"
view thread (6+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH 2/3] Generation: keeper block
In-Reply-To: <no-message-id-1861743@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox