On Thu, 1 Sept 2022 at 08:53, Tomas Vondra <tomas.von...@enterprisedb.com> wrote: > So the raw size (what we asked for) is ~23.5GB, but in practice we > allocate ~28.8GB because of the pow-of-2 logic. And by adding the extra > 1B we end up allocating 31.5GB. That doesn't seem like a huge increase, > and it's far from the +60% you got. > > I wonder where does the difference come - I did make installcheck too, > so how come you get 10/16GB, and I get 28/31GB? My patch is attached, > maybe I did something silly.
The reason my reported results were lower is because I ignored size > allocChunkLimit allocations. These are not raised to the next power of 2, so I didn't think they should be included. I'm not sure why you're seeing only a 3GB additional overhead. I noticed a logic error in my query where I was checking maxaligned_size=pow2_size and doubling that to give sentinel space. That really should have been "case size=pow2_size then pow2_size * 2 else pow2_size end", However, after adjusting the query, it does not seem to change the results much: postgres=# select postgres-# round(sum(pow2_Size)::numeric/1024/1024/1024,3) as pow2_size, postgres-# round(sum(case when size=pow2_size then pow2_size*2 else pow2_size end)::numeric/1024/1024/1024,3) as method1, postgres-# round(sum(case when size=pow2_size then pow2_size+8 else pow2_size end)::numeric/1024/1024/1024,3) as method2 postgres-# from memstats postgres-# where pow2_size > 0; pow2_size | method1 | method2 -----------+---------+--------- 10.269 | 16.322 | 10.476 I've attached the crude patch I came up with for this. For some reason it was crashing on Linux, but it ran ok on Windows, so I used the results from that instead. Maybe that accounts for some differences as e.g sizeof(long) == 4 on 64-bit windows. I'd be surprised if that accounted for so many GBs though. I also forgot to add code to GenerationRealloc and AllocSetRealloc David
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index b6eeb8abab..f4977f9bcc 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -46,6 +46,7 @@ #include "postgres.h" +#include "miscadmin.h" #include "port/pg_bitutils.h" #include "utils/memdebug.h" #include "utils/memutils.h" @@ -696,9 +697,22 @@ AllocSetAlloc(MemoryContext context, Size size) int fidx; Size chunk_size; Size blksize; + static int rlevel = 1; AssertArg(AllocSetIsValid(set)); + if (rlevel == 1 && GetProcessingMode() == NormalProcessing) + { + rlevel++; + elog(LOG, "AllocSetAlloc,%s,%zu,%zu,%zu,%zu", + context->name, + size, + MAXALIGN(size), + size > set->allocChunkLimit ? 0 : GetChunkSizeFromFreeListIdx(AllocSetFreeIndex(size)), + set->allocChunkLimit); + rlevel--; + } + /* * If requested size exceeds maximum for chunks, allocate an entire block * for this request. diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c index b39894ec94..9c5ff3c095 100644 --- a/src/backend/utils/mmgr/generation.c +++ b/src/backend/utils/mmgr/generation.c @@ -36,6 +36,7 @@ #include "postgres.h" #include "lib/ilist.h" +#include "miscadmin.h" #include "port/pg_bitutils.h" #include "utils/memdebug.h" #include "utils/memutils.h" @@ -344,6 +345,18 @@ GenerationAlloc(MemoryContext context, Size size) MemoryChunk *chunk; Size chunk_size = MAXALIGN(size); Size required_size = chunk_size + Generation_CHUNKHDRSZ; + static int rlevel = 1; + + if (rlevel == 1 && GetProcessingMode() == NormalProcessing) + { + rlevel++; + elog(LOG, "GenerationAlloc,%s,%zu,%zu,0,%zu", + context->name, + size, + MAXALIGN(size), + set->allocChunkLimit); + rlevel--; + } /* is it an over-sized chunk? if yes, allocate special block */ if (chunk_size > set->allocChunkLimit)