From 33aaa139e6302e81b4fbf2570be20188bb974c4f Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 6 Jan 2012 14:30:23 -0500 Subject: [PATCH] Make the number of CLOG buffers adaptive, based on shared_buffers. Previously, this was hardcoded: we always had 8. Performance testing shows that isn't enough, especially on big SMP systems, so we allow it to scale up as high as 32 when there's adequate memory. On the flip side, when shared_buffers is very small, drop the number of CLOG buffers down to as little as 4, so that we can start the postmaster even when very little shared memory is available. Per extensive discussion with Simon Riggs, Tom Lane, and others on pgsql-hackers. --- src/backend/access/transam/clog.c | 33 +++++++++++++++++++++++++++++-- src/backend/storage/lmgr/lwlock.c | 2 +- src/include/access/clog.h | 5 +---- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 4060e600ff..69b6ef352b 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -35,6 +35,7 @@ #include "access/clog.h" #include "access/slru.h" #include "access/transam.h" +#include "miscadmin.h" #include "pg_trace.h" /* @@ -409,6 +410,34 @@ TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn) return status; } +/* + * Number of shared CLOG buffers. + * + * Testing during the PostgreSQL 9.2 development cycle revealed that on a + * large multi-processor system, it was possible to have more CLOG page + * requests in flight at one time than the numebr of CLOG buffers which existed + * at that time, which was hardcoded to 8. Further testing revealed that + * performance dropped off with more than 32 CLOG buffers, possibly because + * the linear buffer search algorithm doesn't scale well. + * + * Unconditionally increasing the number of CLOG buffers to 32 did not seem + * like a good idea, because it would increase the minimum amount of shared + * memory required to start, which could be a problem for people running very + * small configurations. The following formula seems to represent a reasonable + * compromise: people with very low values for shared_buffers will get fewer + * CLOG buffers as well, and everyone else will get 32. + * + * It is likely that some further work will be needed here in future releases; + * for example, on a 64-core server, the maximum number of CLOG requests that + * can be simultaneously in flight will be even larger. But that will + * apparently require more than just changing the formula, so for now we take + * the easy way out. + */ +Size +CLOGShmemBuffers(void) +{ + return Min(32, Max(4, NBuffers / 512)); +} /* * Initialization of shared memory for CLOG @@ -416,14 +445,14 @@ TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn) Size CLOGShmemSize(void) { - return SimpleLruShmemSize(NUM_CLOG_BUFFERS, CLOG_LSNS_PER_PAGE); + return SimpleLruShmemSize(CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE); } void CLOGShmemInit(void) { ClogCtl->PagePrecedes = CLOGPagePrecedes; - SimpleLruInit(ClogCtl, "CLOG Ctl", NUM_CLOG_BUFFERS, CLOG_LSNS_PER_PAGE, + SimpleLruInit(ClogCtl, "CLOG Ctl", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE, CLogControlLock, "pg_clog"); } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 96f0d3822e..cc4156826b 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -171,7 +171,7 @@ NumLWLocks(void) numLocks += MaxBackends + NUM_AUXILIARY_PROCS; /* clog.c needs one per CLOG buffer */ - numLocks += NUM_CLOG_BUFFERS; + numLocks += CLOGShmemBuffers(); /* subtrans.c needs one per SubTrans buffer */ numLocks += NUM_SUBTRANS_BUFFERS; diff --git a/src/include/access/clog.h b/src/include/access/clog.h index 9cf54a4486..bed3b8cf26 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -28,14 +28,11 @@ typedef int XidStatus; #define TRANSACTION_STATUS_SUB_COMMITTED 0x03 -/* Number of SLRU buffers to use for clog */ -#define NUM_CLOG_BUFFERS 8 - - extern void TransactionIdSetTreeStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); extern XidStatus TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn); +extern Size CLOGShmemBuffers(void); extern Size CLOGShmemSize(void); extern void CLOGShmemInit(void); extern void BootStrapCLOG(void);