aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-12-27 22:32:03 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-12-27 22:32:03 +0000
commit34aabc20712723fc8a6a3974b724934ea304eaae (patch)
tree8b969938c6f459acfdd21403629a8777c504a415 /src
parentf1d8828e3ce8040e16794fb4d44255d8aef7df34 (diff)
downloadpostgresql-34aabc20712723fc8a6a3974b724934ea304eaae.tar.gz
postgresql-34aabc20712723fc8a6a3974b724934ea304eaae.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/buffer/localbuf.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 38fec03419c..b6f6d89adfa 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.70.2.2 2005/11/22 18:23:18 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.70.2.3 2006/12/27 22:32:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,6 +48,7 @@ static HTAB *LocalBufHash = NULL;
static void InitLocalBuffers(void);
+static Block GetLocalBufferStorage(void);
/*
@@ -167,12 +168,8 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
*/
if (LocalBufHdrGetBlock(bufHdr) == NULL)
{
- char *data;
-
- data = (char *) MemoryContextAlloc(TopMemoryContext, BLCKSZ);
-
/* Set pointer for use by BufferGetBlock() macro */
- LocalBufHdrGetBlock(bufHdr) = (Block) data;
+ LocalBufHdrGetBlock(bufHdr) = GetLocalBufferStorage();
}
/*
@@ -344,6 +341,54 @@ InitLocalBuffers(void)
}
/*
+ * GetLocalBufferStorage - allocate memory for a local buffer
+ *
+ * The idea of this function is to aggregate our requests for storage
+ * so that the memory manager doesn't see a whole lot of relatively small
+ * requests. Since we'll never give back a local buffer once it's created
+ * within a particular process, no point in burdening memmgr with separately
+ * managed chunks.
+ */
+static Block
+GetLocalBufferStorage(void)
+{
+ static char *cur_block = NULL;
+ static int next_buf_in_block = 0;
+ static int num_bufs_in_block = 0;
+ static int total_bufs_allocated = 0;
+
+ char *this_buf;
+
+ Assert(total_bufs_allocated < NLocBuffer);
+
+ if (next_buf_in_block >= num_bufs_in_block)
+ {
+ /* Need to make a new request to memmgr */
+ int num_bufs;
+
+ /* Start with a 16-buffer request; subsequent ones double each time */
+ num_bufs = Max(num_bufs_in_block * 2, 16);
+ /* But not more than what we need for all remaining local bufs */
+ num_bufs = Min(num_bufs, NLocBuffer - total_bufs_allocated);
+ /* And don't overflow MaxAllocSize, either */
+ num_bufs = Min(num_bufs, MaxAllocSize / BLCKSZ);
+
+ /* Allocate space from TopMemoryContext so it never goes away */
+ cur_block = (char *) MemoryContextAlloc(TopMemoryContext,
+ num_bufs * BLCKSZ);
+ next_buf_in_block = 0;
+ num_bufs_in_block = num_bufs;
+ }
+
+ /* Allocate next buffer in current memory block */
+ this_buf = cur_block + next_buf_in_block * BLCKSZ;
+ next_buf_in_block++;
+ total_bufs_allocated++;
+
+ return (Block) this_buf;
+}
+
+/*
* AtEOXact_LocalBuffers - clean up at end of transaction.
*
* This is just like AtEOXact_Buffers, but for local buffers.