agora inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feedFrom: Tomas Vondra <tomas.vondra@postgresql.org>
Subject: [PATCH 2/4] Generation: grow blocks
Date: Fri, 30 Jul 2021 23:53:52 +0200
---
contrib/generation_bench/generation_bench.c | 6 +--
src/backend/access/gist/gistvacuum.c | 2 +-
.../replication/logical/reorderbuffer.c | 2 +-
src/backend/utils/mmgr/generation.c | 53 ++++++++++++++-----
src/include/utils/memutils.h | 4 +-
5 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/contrib/generation_bench/generation_bench.c b/contrib/generation_bench/generation_bench.c
index f86aaaa041..bb058a7f1d 100644
--- a/contrib/generation_bench/generation_bench.c
+++ b/contrib/generation_bench/generation_bench.c
@@ -91,7 +91,7 @@ generation_bench_random(PG_FUNCTION_ARGS)
maxchunks = nallocs + nloops * Max(0, alloc_cnt - free_cnt);
- cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize);
+ cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize, blockSize, 1024L * 1024L);
chunks = (Chunk *) palloc(maxchunks * sizeof(Chunk));
@@ -229,7 +229,7 @@ generation_bench_fifo(PG_FUNCTION_ARGS)
maxchunks = nallocs + nloops * Max(0, alloc_cnt - free_cnt);
- cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize);
+ cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize, blockSize, 1024L * 1024L);
chunks = (Chunk *) palloc(maxchunks * sizeof(Chunk));
@@ -354,7 +354,7 @@ generation_bench_lifo(PG_FUNCTION_ARGS)
maxchunks = nallocs + nloops * Max(0, alloc_cnt - free_cnt);
- cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize);
+ cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize, blockSize, 1024L * 1024L);
chunks = (Chunk *) palloc(maxchunks * sizeof(Chunk));
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 0663193531..1818ed06fc 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -161,7 +161,7 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
*/
vstate.page_set_context = GenerationContextCreate(CurrentMemoryContext,
"GiST VACUUM page set context",
- 16 * 1024);
+ ALLOCSET_DEFAULT_SIZES);
oldctx = MemoryContextSwitchTo(vstate.page_set_context);
vstate.internal_page_set = intset_create();
vstate.empty_leaf_set = intset_create();
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 7378beb684..308d833292 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -329,7 +329,7 @@ ReorderBufferAllocate(void)
buffer->tup_context = GenerationContextCreate(new_ctx,
"Tuples",
- SLAB_LARGE_BLOCK_SIZE);
+ ALLOCSET_DEFAULT_SIZES);
hash_ctl.keysize = sizeof(TransactionId);
hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 584cd614da..771a2525ca 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -60,7 +60,9 @@ typedef struct GenerationContext
MemoryContextData header; /* Standard memory-context fields */
/* Generational context parameters */
- Size blockSize; /* standard block size */
+ Size initBlockSize; /* initial block size */
+ Size maxBlockSize; /* maximum block size */
+ Size nextBlockSize; /* next block size to allocate */
GenerationBlock *block; /* current (most recently allocated) block */
dlist_head blocks; /* list of blocks */
@@ -196,7 +198,9 @@ static const MemoryContextMethods GenerationMethods = {
MemoryContext
GenerationContextCreate(MemoryContext parent,
const char *name,
- Size blockSize)
+ Size minContextSize,
+ Size initBlockSize,
+ Size maxBlockSize)
{
GenerationContext *set;
@@ -208,16 +212,20 @@ GenerationContextCreate(MemoryContext parent,
"padding calculation in GenerationChunk is wrong");
/*
- * First, validate allocation parameters. (If we're going to throw an
- * error, we should do so before the context is created, not after.) We
- * somewhat arbitrarily enforce a minimum 1K block size, mostly because
- * that's what AllocSet does.
+ * First, validate allocation parameters. Once these were regular runtime
+ * test and elog's, but in practice Asserts seem sufficient because nobody
+ * varies their parameters at runtime. We somewhat arbitrarily enforce a
+ * minimum 1K block size.
*/
- if (blockSize != MAXALIGN(blockSize) ||
- blockSize < 1024 ||
- !AllocHugeSizeIsValid(blockSize))
- elog(ERROR, "invalid blockSize for memory context: %zu",
- blockSize);
+ Assert(initBlockSize == MAXALIGN(initBlockSize) &&
+ initBlockSize >= 1024);
+ Assert(maxBlockSize == MAXALIGN(maxBlockSize) &&
+ maxBlockSize >= initBlockSize &&
+ AllocHugeSizeIsValid(maxBlockSize)); /* must be safe to double */
+ Assert(minContextSize == 0 ||
+ (minContextSize == MAXALIGN(minContextSize) &&
+ minContextSize >= 1024 &&
+ minContextSize <= maxBlockSize));
/*
* Allocate the context header. Unlike aset.c, we never try to combine
@@ -242,7 +250,9 @@ GenerationContextCreate(MemoryContext parent,
*/
/* Fill in GenerationContext-specific header fields */
- set->blockSize = blockSize;
+ set->initBlockSize = initBlockSize;
+ set->maxBlockSize = maxBlockSize;
+ set->nextBlockSize = initBlockSize;
set->block = NULL;
dlist_init(&set->blocks);
@@ -293,6 +303,9 @@ GenerationReset(MemoryContext context)
set->block = NULL;
+ /* Reset block size allocation sequence, too */
+ set->nextBlockSize = set->initBlockSize;
+
Assert(dlist_is_empty(&set->blocks));
}
@@ -329,9 +342,12 @@ GenerationAlloc(MemoryContext context, Size size)
GenerationBlock *block;
GenerationChunk *chunk;
Size chunk_size = MAXALIGN(size);
+ Size blockSize;
+
+ blockSize = (set->block) ? set->block->blksize : set->nextBlockSize;
/* is it an over-sized chunk? if yes, allocate special block */
- if (chunk_size > set->blockSize / 8)
+ if (chunk_size > (blockSize / 8))
{
Size blksize = chunk_size + Generation_BLOCKHDRSZ + Generation_CHUNKHDRSZ;
@@ -387,7 +403,16 @@ GenerationAlloc(MemoryContext context, Size size)
if ((block == NULL) ||
(block->endptr - block->freeptr) < Generation_CHUNKHDRSZ + chunk_size)
{
- Size blksize = set->blockSize;
+ Size blksize;
+
+ /*
+ * The first such block has size initBlockSize, and we double the
+ * space in each succeeding block, but not more than maxBlockSize.
+ */
+ blksize = set->nextBlockSize;
+ set->nextBlockSize <<= 1;
+ if (set->nextBlockSize > set->maxBlockSize)
+ set->nextBlockSize = set->maxBlockSize;
block = (GenerationBlock *) malloc(blksize);
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index ff872274d4..514c0bf75b 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -183,7 +183,9 @@ extern MemoryContext SlabContextCreate(MemoryContext parent,
/* generation.c */
extern MemoryContext GenerationContextCreate(MemoryContext parent,
const char *name,
- Size blockSize);
+ Size minContextSize,
+ Size initBlockSize,
+ Size maxBlockSize);
/*
* Recommended default alloc parameters, suitable for "ordinary" contexts
--
2.31.1
--------------D082F723AC01DF154D86FBFF
Content-Type: text/x-patch; charset=UTF-8;
name="0003-Generation-keeper-block.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0003-Generation-keeper-block.patch"
view thread (4+ 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: pgsql-hackers@postgresql.org
Cc: tomas.vondra@postgresql.org
Subject: Re: [PATCH 2/4] Generation: grow blocks
In-Reply-To: <no-message-id-1861086@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