Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4ce4c76

Browse files
david-rowleypull[bot]
authored andcommitted
Shrink memory contexts struct sizes
Here we reduce the block size fields in AllocSetContext, GenerationContextand SlabContext from Size down to uint32. Ever sincec6e0fe1, blocksfor non-dedicated palloc chunks can no longer be larger than 1GB, sothere's no need to store the various block size fields as 64-bit values.32 bits are enough to store 2^30.Here we also further reduce the memory context struct sizes by getting ridof the 'keeper' field which stores a pointer to the context's keeperblock. All the context types which have this field always allocate thekeeper block in the same allocation as the memory context itself, so thekeeper block always comes right at the end of the context struct. Addsome macros to calculate that address rather than storing it in thecontext.Overall, in AllocSetContext and GenerationContext, this saves 20 bytes on64-bit builds which for ALLOCSET_SMALL_SIZES can sometimes mean thedifference between having to allocate a 2nd block and storing all therequired allocations on the keeper block alone. Such contexts are usedin relcache to store cache entries for indexes, of which there can bea large number in a single backend.Author: Melih MutluReviewed-by: David RowleyDiscussion:https://postgr.es/m/CAGPVpCSOW3uJ1QJmsMR9_oE3X7fG_z4q0AoU4R_w+2RzvroPFg@mail.gmail.com
1 parentb63a552 commit4ce4c76

File tree

3 files changed

+60
-48
lines changed

3 files changed

+60
-48
lines changed

‎src/backend/utils/mmgr/aset.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,10 @@ typedef struct AllocSetContext
156156
AllocBlockblocks;/* head of list of blocks in this set */
157157
MemoryChunk*freelist[ALLOCSET_NUM_FREELISTS];/* free chunk lists */
158158
/* Allocation parameters for this context: */
159-
SizeinitBlockSize;/* initial block size */
160-
SizemaxBlockSize;/* maximum block size */
161-
SizenextBlockSize;/* next block size to allocate */
162-
SizeallocChunkLimit;/* effective chunk size limit */
163-
AllocBlockkeeper;/* keep this block over resets */
159+
uint32initBlockSize;/* initial block size */
160+
uint32maxBlockSize;/* maximum block size */
161+
uint32nextBlockSize;/* next block size to allocate */
162+
uint32allocChunkLimit;/* effective chunk size limit */
164163
/* freelist this context could be put in, or -1 if not a candidate: */
165164
intfreeListIndex;/* index in context_freelists[], or -1 */
166165
}AllocSetContext;
@@ -241,6 +240,13 @@ typedef struct AllocBlockData
241240
*/
242241
#defineMAX_FREE_CONTEXTS 100/* arbitrary limit on freelist length */
243242

243+
/* Obtain the keeper block for an allocation set */
244+
#defineKeeperBlock(set) \
245+
((AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext))))
246+
247+
/* Check if the block is the keeper block of the given allocation set */
248+
#defineIsKeeperBlock(set,block) ((block) == (KeeperBlock(set)))
249+
244250
typedefstructAllocSetFreeList
245251
{
246252
intnum_free;/* current list length */
@@ -417,7 +423,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
417423
name);
418424

419425
((MemoryContext)set)->mem_allocated=
420-
set->keeper->endptr- ((char*)set);
426+
KeeperBlock(set)->endptr- ((char*)set);
421427

422428
return (MemoryContext)set;
423429
}
@@ -453,7 +459,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
453459
*/
454460

455461
/* Fill in the initial block's block header */
456-
block=(AllocBlock) (((char*)set)+MAXALIGN(sizeof(AllocSetContext)));
462+
block=KeeperBlock(set);
457463
block->aset=set;
458464
block->freeptr= ((char*)block)+ALLOC_BLOCKHDRSZ;
459465
block->endptr= ((char*)set)+firstBlockSize;
@@ -465,15 +471,13 @@ AllocSetContextCreateInternal(MemoryContext parent,
465471

466472
/* Remember block as part of block list */
467473
set->blocks=block;
468-
/* Mark block as not to be released at reset time */
469-
set->keeper=block;
470474

471475
/* Finish filling in aset-specific parts of the context header */
472476
MemSetAligned(set->freelist,0,sizeof(set->freelist));
473477

474-
set->initBlockSize=initBlockSize;
475-
set->maxBlockSize=maxBlockSize;
476-
set->nextBlockSize=initBlockSize;
478+
set->initBlockSize=(uint32)initBlockSize;
479+
set->maxBlockSize=(uint32)maxBlockSize;
480+
set->nextBlockSize=(uint32)initBlockSize;
477481
set->freeListIndex=freeListIndex;
478482

479483
/*
@@ -544,21 +548,21 @@ AllocSetReset(MemoryContext context)
544548
#endif
545549

546550
/* Remember keeper block size for Assert below */
547-
keepersize=set->keeper->endptr- ((char*)set);
551+
keepersize=KeeperBlock(set)->endptr- ((char*)set);
548552

549553
/* Clear chunk freelists */
550554
MemSetAligned(set->freelist,0,sizeof(set->freelist));
551555

552556
block=set->blocks;
553557

554558
/* New blocks list will be just the keeper block */
555-
set->blocks=set->keeper;
559+
set->blocks=KeeperBlock(set);
556560

557561
while (block!=NULL)
558562
{
559563
AllocBlocknext=block->next;
560564

561-
if (block==set->keeper)
565+
if (IsKeeperBlock(set,block))
562566
{
563567
/* Reset the block, but don't return it to malloc */
564568
char*datastart= ((char*)block)+ALLOC_BLOCKHDRSZ;
@@ -614,7 +618,7 @@ AllocSetDelete(MemoryContext context)
614618
#endif
615619

616620
/* Remember keeper block size for Assert below */
617-
keepersize=set->keeper->endptr- ((char*)set);
621+
keepersize=KeeperBlock(set)->endptr- ((char*)set);
618622

619623
/*
620624
* If the context is a candidate for a freelist, put it into that freelist
@@ -663,14 +667,14 @@ AllocSetDelete(MemoryContext context)
663667
{
664668
AllocBlocknext=block->next;
665669

666-
if (block!=set->keeper)
670+
if (!IsKeeperBlock(set,block))
667671
context->mem_allocated-=block->endptr- ((char*)block);
668672

669673
#ifdefCLOBBER_FREED_MEMORY
670674
wipe_mem(block,block->freeptr- ((char*)block));
671675
#endif
672676

673-
if (block!=set->keeper)
677+
if (!IsKeeperBlock(set,block))
674678
free(block);
675679

676680
block=next;
@@ -1547,7 +1551,7 @@ AllocSetCheck(MemoryContext context)
15471551
longnchunks=0;
15481552
boolhas_external_chunk= false;
15491553

1550-
if (set->keeper==block)
1554+
if (IsKeeperBlock(set,block))
15511555
total_allocated+=block->endptr- ((char*)set);
15521556
else
15531557
total_allocated+=block->endptr- ((char*)block);
@@ -1557,7 +1561,7 @@ AllocSetCheck(MemoryContext context)
15571561
*/
15581562
if (!blk_used)
15591563
{
1560-
if (set->keeper!=block)
1564+
if (!IsKeeperBlock(set,block))
15611565
elog(WARNING,"problem in alloc set %s: empty block %p",
15621566
name,block);
15631567
}

‎src/backend/utils/mmgr/generation.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,16 @@ typedef struct GenerationContext
6161
MemoryContextDataheader;/* Standard memory-context fields */
6262

6363
/* Generational context parameters */
64-
SizeinitBlockSize;/* initial block size */
65-
SizemaxBlockSize;/* maximum block size */
66-
SizenextBlockSize;/* next block size to allocate */
67-
SizeallocChunkLimit;/* effective chunk size limit */
64+
uint32initBlockSize;/* initial block size */
65+
uint32maxBlockSize;/* maximum block size */
66+
uint32nextBlockSize;/* next block size to allocate */
67+
uint32allocChunkLimit;/* effective chunk size limit */
6868

6969
GenerationBlock*block;/* current (most recently allocated) block, or
7070
* NULL if we've just freed the most recent
7171
* block */
7272
GenerationBlock*freeblock;/* pointer to a block that's being recycled,
7373
* or NULL if there's no such block. */
74-
GenerationBlock*keeper;/* keep this block over resets */
7574
dlist_headblocks;/* list of blocks */
7675
}GenerationContext;
7776

@@ -120,6 +119,14 @@ struct GenerationBlock
120119
#defineExternalChunkGetBlock(chunk) \
121120
(GenerationBlock *) ((char *) chunk - Generation_BLOCKHDRSZ)
122121

122+
/* Obtain the keeper block for a generation context */
123+
#defineKeeperBlock(set) \
124+
((GenerationBlock *) (((char *) set) + \
125+
MAXALIGN(sizeof(GenerationContext))))
126+
127+
/* Check if the block is the keeper block of the given generation context */
128+
#defineIsKeeperBlock(set,block) ((block) == (KeeperBlock(set)))
129+
123130
/* Inlined helper functions */
124131
staticinlinevoidGenerationBlockInit(GenerationContext*context,
125132
GenerationBlock*block,
@@ -214,7 +221,7 @@ GenerationContextCreate(MemoryContext parent,
214221
dlist_init(&set->blocks);
215222

216223
/* Fill in the initial block's block header */
217-
block=(GenerationBlock*) (((char*)set)+MAXALIGN(sizeof(GenerationContext)));
224+
block=KeeperBlock(set);
218225
/* determine the block size and initialize it */
219226
firstBlockSize=allocSize-MAXALIGN(sizeof(GenerationContext));
220227
GenerationBlockInit(set,block,firstBlockSize);
@@ -228,13 +235,10 @@ GenerationContextCreate(MemoryContext parent,
228235
/* No free block, yet */
229236
set->freeblock=NULL;
230237

231-
/* Mark block as not to be released at reset time */
232-
set->keeper=block;
233-
234238
/* Fill in GenerationContext-specific header fields */
235-
set->initBlockSize=initBlockSize;
236-
set->maxBlockSize=maxBlockSize;
237-
set->nextBlockSize=initBlockSize;
239+
set->initBlockSize=(uint32)initBlockSize;
240+
set->maxBlockSize=(uint32)maxBlockSize;
241+
set->nextBlockSize=(uint32)initBlockSize;
238242

239243
/*
240244
* Compute the allocation chunk size limit for this context.
@@ -294,14 +298,14 @@ GenerationReset(MemoryContext context)
294298
{
295299
GenerationBlock*block=dlist_container(GenerationBlock,node,miter.cur);
296300

297-
if (block==set->keeper)
301+
if (IsKeeperBlock(set,block))
298302
GenerationBlockMarkEmpty(block);
299303
else
300304
GenerationBlockFree(set,block);
301305
}
302306

303307
/* set it so new allocations to make use of the keeper block */
304-
set->block=set->keeper;
308+
set->block=KeeperBlock(set);
305309

306310
/* Reset block size allocation sequence, too */
307311
set->nextBlockSize=set->initBlockSize;
@@ -440,10 +444,10 @@ GenerationAlloc(MemoryContext context, Size size)
440444
*/
441445
set->freeblock=NULL;
442446
}
443-
elseif (GenerationBlockIsEmpty(set->keeper)&&
444-
GenerationBlockFreeBytes(set->keeper) >=required_size)
447+
elseif (GenerationBlockIsEmpty(KeeperBlock(set))&&
448+
GenerationBlockFreeBytes(KeeperBlock(set)) >=required_size)
445449
{
446-
block=set->keeper;
450+
block=KeeperBlock(set);
447451
}
448452
else
449453
{
@@ -594,7 +598,7 @@ static inline void
594598
GenerationBlockFree(GenerationContext*set,GenerationBlock*block)
595599
{
596600
/* Make sure nobody tries to free the keeper block */
597-
Assert(block!=set->keeper);
601+
Assert(!IsKeeperBlock(set,block));
598602
/* We shouldn't be freeing the freeblock either */
599603
Assert(block!=set->freeblock);
600604

@@ -691,7 +695,7 @@ GenerationFree(void *pointer)
691695
set=block->context;
692696

693697
/* Don't try to free the keeper block, just mark it empty */
694-
if (block==set->keeper)
698+
if (IsKeeperBlock(set,block))
695699
{
696700
GenerationBlockMarkEmpty(block);
697701
return;

‎src/backend/utils/mmgr/slab.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ typedef struct SlabContext
104104
{
105105
MemoryContextDataheader;/* Standard memory-context fields */
106106
/* Allocation parameters for this context: */
107-
SizechunkSize;/* the requested (non-aligned) chunk size */
108-
SizefullChunkSize;/* chunk size with chunk header and alignment */
109-
SizeblockSize;/* the size to make each block of chunks */
107+
uint32chunkSize;/* the requested (non-aligned) chunk size */
108+
uint32fullChunkSize;/* chunk size with chunk header and alignment */
109+
uint32blockSize;/* the size to make each block of chunks */
110110
int32chunksPerBlock;/* number of chunks that fit in 1 block */
111111
int32curBlocklistIndex;/* index into the blocklist[] element
112112
* containing the fullest, blocks */
@@ -314,7 +314,9 @@ SlabGetNextFreeChunk(SlabContext *slab, SlabBlock *block)
314314
* blockSize: allocation block size
315315
* chunkSize: allocation chunk size
316316
*
317-
* The MAXALIGN(chunkSize) may not exceed MEMORYCHUNK_MAX_VALUE
317+
* The Slab_CHUNKHDRSZ + MAXALIGN(chunkSize + 1) may not exceed
318+
* MEMORYCHUNK_MAX_VALUE.
319+
* 'blockSize' may not exceed MEMORYCHUNK_MAX_BLOCKOFFSET.
318320
*/
319321
MemoryContext
320322
SlabContextCreate(MemoryContextparent,
@@ -330,7 +332,7 @@ SlabContextCreate(MemoryContext parent,
330332
/* ensure MemoryChunk's size is properly maxaligned */
331333
StaticAssertDecl(Slab_CHUNKHDRSZ==MAXALIGN(Slab_CHUNKHDRSZ),
332334
"sizeof(MemoryChunk) is not maxaligned");
333-
Assert(MAXALIGN(chunkSize) <=MEMORYCHUNK_MAX_VALUE);
335+
Assert(blockSize <=MEMORYCHUNK_MAX_BLOCKOFFSET);
334336

335337
/*
336338
* Ensure there's enough space to store the pointer to the next free chunk
@@ -347,6 +349,8 @@ SlabContextCreate(MemoryContext parent,
347349
fullChunkSize=Slab_CHUNKHDRSZ+MAXALIGN(chunkSize);
348350
#endif
349351

352+
Assert(fullChunkSize <=MEMORYCHUNK_MAX_VALUE);
353+
350354
/* compute the number of chunks that will fit on each block */
351355
chunksPerBlock= (blockSize-Slab_BLOCKHDRSZ) /fullChunkSize;
352356

@@ -374,9 +378,9 @@ SlabContextCreate(MemoryContext parent,
374378
*/
375379

376380
/* Fill in SlabContext-specific header fields */
377-
slab->chunkSize=chunkSize;
378-
slab->fullChunkSize=fullChunkSize;
379-
slab->blockSize=blockSize;
381+
slab->chunkSize=(uint32)chunkSize;
382+
slab->fullChunkSize=(uint32)fullChunkSize;
383+
slab->blockSize=(uint32)blockSize;
380384
slab->chunksPerBlock=chunksPerBlock;
381385
slab->curBlocklistIndex=0;
382386

@@ -506,7 +510,7 @@ SlabAlloc(MemoryContext context, Size size)
506510

507511
/* make sure we only allow correct request size */
508512
if (unlikely(size!=slab->chunkSize))
509-
elog(ERROR,"unexpected alloc chunk size %zu (expected %zu)",
513+
elog(ERROR,"unexpected alloc chunk size %zu (expected %u)",
510514
size,slab->chunkSize);
511515

512516
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp