Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)