Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 72619f8

Browse files
committed
Modify local buffer management to request memory for local buffers in blocks
of increasing size, instead of one at a time. This reduces the memory management overhead when num_temp_buffers is large: in the previous coding we would actually waste 50% of the space used for temp buffers, because aset.c would round the individual requests up to 16K. Problem noted while studying a performance issue reported by Steven Flatt. Back-patch as far as 8.1 --- older versions used few enough local buffers that the issue isn't significant for them.
1 parent c22dea8 commit 72619f8

File tree

1 file changed

+51
-6
lines changed

1 file changed

+51
-6
lines changed

src/backend/storage/buffer/localbuf.c

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.74 2006/03/31 23:32:06 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.75 2006/12/27 22:31:54 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -48,6 +48,7 @@ static HTAB *LocalBufHash = NULL;
4848

4949

5050
static void InitLocalBuffers(void);
51+
static Block GetLocalBufferStorage(void);
5152

5253

5354
/*
@@ -167,12 +168,8 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
167168
*/
168169
if (LocalBufHdrGetBlock(bufHdr) == NULL)
169170
{
170-
char *data;
171-
172-
data = (char *) MemoryContextAlloc(TopMemoryContext, BLCKSZ);
173-
174171
/* Set pointer for use by BufferGetBlock() macro */
175-
LocalBufHdrGetBlock(bufHdr) = (Block) data;
172+
LocalBufHdrGetBlock(bufHdr) = GetLocalBufferStorage();
176173
}
177174

178175
/*
@@ -334,6 +331,54 @@ InitLocalBuffers(void)
334331
NLocBuffer = nbufs;
335332
}
336333

334+
/*
335+
* GetLocalBufferStorage - allocate memory for a local buffer
336+
*
337+
* The idea of this function is to aggregate our requests for storage
338+
* so that the memory manager doesn't see a whole lot of relatively small
339+
* requests. Since we'll never give back a local buffer once it's created
340+
* within a particular process, no point in burdening memmgr with separately
341+
* managed chunks.
342+
*/
343+
static Block
344+
GetLocalBufferStorage(void)
345+
{
346+
static char *cur_block = NULL;
347+
static int next_buf_in_block = 0;
348+
static int num_bufs_in_block = 0;
349+
static int total_bufs_allocated = 0;
350+
351+
char *this_buf;
352+
353+
Assert(total_bufs_allocated < NLocBuffer);
354+
355+
if (next_buf_in_block >= num_bufs_in_block)
356+
{
357+
/* Need to make a new request to memmgr */
358+
int num_bufs;
359+
360+
/* Start with a 16-buffer request; subsequent ones double each time */
361+
num_bufs = Max(num_bufs_in_block * 2, 16);
362+
/* But not more than what we need for all remaining local bufs */
363+
num_bufs = Min(num_bufs, NLocBuffer - total_bufs_allocated);
364+
/* And don't overflow MaxAllocSize, either */
365+
num_bufs = Min(num_bufs, MaxAllocSize / BLCKSZ);
366+
367+
/* Allocate space from TopMemoryContext so it never goes away */
368+
cur_block = (char *) MemoryContextAlloc(TopMemoryContext,
369+
num_bufs * BLCKSZ);
370+
next_buf_in_block = 0;
371+
num_bufs_in_block = num_bufs;
372+
}
373+
374+
/* Allocate next buffer in current memory block */
375+
this_buf = cur_block + next_buf_in_block * BLCKSZ;
376+
next_buf_in_block++;
377+
total_bufs_allocated++;
378+
379+
return (Block) this_buf;
380+
}
381+
337382
/*
338383
* AtEOXact_LocalBuffers - clean up at end of transaction.
339384
*

0 commit comments

Comments
 (0)