diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 22e2c0541e..a3ab916bd6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -24,7 +24,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.35 2005/12/06 18:10:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.36 2005/12/06 23:08:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -147,14 +147,15 @@ TransactionIdGetStatus(TransactionId xid) Size CLOGShmemSize(void) { - return SimpleLruShmemSize(); + return SimpleLruShmemSize(NUM_CLOG_BUFFERS); } void CLOGShmemInit(void) { ClogCtl->PagePrecedes = CLOGPagePrecedes; - SimpleLruInit(ClogCtl, "CLOG Ctl", CLogControlLock, "pg_clog"); + SimpleLruInit(ClogCtl, "CLOG Ctl", NUM_CLOG_BUFFERS, + CLogControlLock, "pg_clog"); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 3e8f86818f..1862d188b3 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.14 2005/12/06 18:10:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.15 2005/12/06 23:08:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1249,8 +1249,8 @@ MultiXactShmemSize(void) mul_size(sizeof(MultiXactId) * 2, MaxBackends)) size = SHARED_MULTIXACT_STATE_SIZE; - size = add_size(size, SimpleLruShmemSize()); - size = add_size(size, SimpleLruShmemSize()); + size = add_size(size, SimpleLruShmemSize(NUM_MXACTOFFSET_BUFFERS)); + size = add_size(size, SimpleLruShmemSize(NUM_MXACTMEMBER_BUFFERS)); return size; } @@ -1265,9 +1265,11 @@ MultiXactShmemInit(void) MultiXactOffsetCtl->PagePrecedes = MultiXactOffsetPagePrecedes; MultiXactMemberCtl->PagePrecedes = MultiXactMemberPagePrecedes; - SimpleLruInit(MultiXactOffsetCtl, "MultiXactOffset Ctl", + SimpleLruInit(MultiXactOffsetCtl, + "MultiXactOffset Ctl", NUM_MXACTOFFSET_BUFFERS, MultiXactOffsetControlLock, "pg_multixact/offsets"); - SimpleLruInit(MultiXactMemberCtl, "MultiXactMember Ctl", + SimpleLruInit(MultiXactMemberCtl, + "MultiXactMember Ctl", NUM_MXACTMEMBER_BUFFERS, MultiXactMemberControlLock, "pg_multixact/members"); /* Initialize our shared state struct */ diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 901a5e57da..d1bfd9570c 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -41,7 +41,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.32 2005/12/06 18:10:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.33 2005/12/06 23:08:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,11 +87,13 @@ * until control returns to SimpleLruFlush(). This data structure remembers * which files are open. */ +#define MAX_FLUSH_BUFFERS 16 + typedef struct SlruFlushData { - int num_files; /* # files actually open */ - int fd[NUM_SLRU_BUFFERS]; /* their FD's */ - int segno[NUM_SLRU_BUFFERS]; /* their log seg#s */ + int num_files; /* # files actually open */ + int fd[MAX_FLUSH_BUFFERS]; /* their FD's */ + int segno[MAX_FLUSH_BUFFERS]; /* their log seg#s */ } SlruFlushData; /* @@ -150,25 +152,38 @@ static int SlruSelectLRUPage(SlruCtl ctl, int pageno); */ Size -SimpleLruShmemSize(void) +SimpleLruShmemSize(int nslots) { - /* we assume NUM_SLRU_BUFFERS isn't so large as to risk overflow */ - return BUFFERALIGN(sizeof(SlruSharedData)) + BLCKSZ * NUM_SLRU_BUFFERS; + Size sz; + + /* we assume nslots isn't so large as to risk overflow */ + sz = MAXALIGN(sizeof(SlruSharedData)); + sz += MAXALIGN(nslots * sizeof(char *)); /* page_buffer[] */ + sz += MAXALIGN(nslots * sizeof(SlruPageStatus)); /* page_status[] */ + sz += MAXALIGN(nslots * sizeof(bool)); /* page_dirty[] */ + sz += MAXALIGN(nslots * sizeof(int)); /* page_number[] */ + sz += MAXALIGN(nslots * sizeof(int)); /* page_lru_count[] */ + sz += MAXALIGN(nslots * sizeof(LWLockId)); /* buffer_locks[] */ + + return BUFFERALIGN(sz) + BLCKSZ * nslots; } void -SimpleLruInit(SlruCtl ctl, const char *name, +SimpleLruInit(SlruCtl ctl, const char *name, int nslots, LWLockId ctllock, const char *subdir) { SlruShared shared; bool found; - shared = (SlruShared) ShmemInitStruct(name, SimpleLruShmemSize(), &found); + shared = (SlruShared) ShmemInitStruct(name, + SimpleLruShmemSize(nslots), + &found); if (!IsUnderPostmaster) { /* Initialize locks and shared memory area */ - char *bufptr; + char *ptr; + Size offset; int slotno; Assert(!found); @@ -177,19 +192,37 @@ SimpleLruInit(SlruCtl ctl, const char *name, shared->ControlLock = ctllock; - bufptr = (char *) shared + BUFFERALIGN(sizeof(SlruSharedData)); + shared->num_slots = nslots; - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + shared->cur_lru_count = 0; + + /* shared->latest_page_number will be set later */ + + ptr = (char *) shared; + offset = MAXALIGN(sizeof(SlruSharedData)); + shared->page_buffer = (char **) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(char *)); + shared->page_status = (SlruPageStatus *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(SlruPageStatus)); + shared->page_dirty = (bool *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(bool)); + shared->page_number = (int *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(int)); + shared->page_lru_count = (int *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(int)); + shared->buffer_locks = (LWLockId *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(LWLockId)); + ptr += BUFFERALIGN(offset); + + for (slotno = 0; slotno < nslots; slotno++) { - shared->page_buffer[slotno] = bufptr; + shared->page_buffer[slotno] = ptr; shared->page_status[slotno] = SLRU_PAGE_EMPTY; shared->page_dirty[slotno] = false; shared->page_lru_count[slotno] = 0; shared->buffer_locks[slotno] = LWLockAssign(); - bufptr += BLCKSZ; + ptr += BLCKSZ; } - - /* shared->latest_page_number will be set later */ } else Assert(found); @@ -394,7 +427,7 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid) LWLockAcquire(shared->ControlLock, LW_SHARED); /* See if page is already in a buffer */ - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { if (shared->page_number[slotno] == pageno && shared->page_status[slotno] != SLRU_PAGE_EMPTY && @@ -643,9 +676,20 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) if (fdata) { - fdata->fd[fdata->num_files] = fd; - fdata->segno[fdata->num_files] = segno; - fdata->num_files++; + if (fdata->num_files < MAX_FLUSH_BUFFERS) + { + fdata->fd[fdata->num_files] = fd; + fdata->segno[fdata->num_files] = segno; + fdata->num_files++; + } + else + { + /* + * In the unlikely event that we exceed MAX_FLUSH_BUFFERS, + * fall back to treating it as a standalone write. + */ + fdata = NULL; + } } } @@ -797,7 +841,7 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno) int best_page_number; /* See if page already has a buffer assigned */ - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { if (shared->page_number[slotno] == pageno && shared->page_status[slotno] != SLRU_PAGE_EMPTY) @@ -830,7 +874,7 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno) best_delta = -1; bestslot = 0; /* no-op, just keeps compiler quiet */ best_page_number = 0; /* ditto */ - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { int this_delta; int this_page_number; @@ -908,7 +952,7 @@ SimpleLruFlush(SlruCtl ctl, bool checkpoint) LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE); - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { SimpleLruWritePage(ctl, slotno, &fdata); @@ -990,7 +1034,7 @@ restart:; return; } - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { if (shared->page_status[slotno] == SLRU_PAGE_EMPTY) continue; diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c index bb32550cfc..03d0543686 100644 --- a/src/backend/access/transam/subtrans.c +++ b/src/backend/access/transam/subtrans.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.14 2005/12/06 18:10:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.15 2005/12/06 23:08:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -164,14 +164,14 @@ SubTransGetTopmostTransaction(TransactionId xid) Size SUBTRANSShmemSize(void) { - return SimpleLruShmemSize(); + return SimpleLruShmemSize(NUM_SUBTRANS_BUFFERS); } void SUBTRANSShmemInit(void) { SubTransCtl->PagePrecedes = SubTransPagePrecedes; - SimpleLruInit(SubTransCtl, "SUBTRANS Ctl", + SimpleLruInit(SubTransCtl, "SUBTRANS Ctl", NUM_SUBTRANS_BUFFERS, SubtransControlLock, "pg_subtrans"); /* Override default assumption that writes should be fsync'd */ SubTransCtl->do_fsync = false; diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 5526c77a67..a215a65285 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -15,13 +15,15 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.34 2005/10/15 02:49:26 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.35 2005/12/06 23:08:33 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include "access/slru.h" +#include "access/clog.h" +#include "access/multixact.h" +#include "access/subtrans.h" #include "storage/lwlock.h" #include "storage/proc.h" #include "storage/spin.h" @@ -129,16 +131,13 @@ NumLWLocks(void) numLocks += 2 * NBuffers; /* clog.c needs one per CLOG buffer */ - numLocks += NUM_SLRU_BUFFERS; + numLocks += NUM_CLOG_BUFFERS; /* subtrans.c needs one per SubTrans buffer */ - numLocks += NUM_SLRU_BUFFERS; + numLocks += NUM_SUBTRANS_BUFFERS; - /* - * multixact.c needs one per MultiXact buffer, but there are two SLRU - * areas for MultiXact - */ - numLocks += 2 * NUM_SLRU_BUFFERS; + /* multixact.c needs two SLRU areas */ + numLocks += NUM_MXACTOFFSET_BUFFERS + NUM_MXACTMEMBER_BUFFERS; /* Leave a few extra for use by user-defined modules. */ numLocks += NUM_USER_DEFINED_LWLOCKS; diff --git a/src/include/access/clog.h b/src/include/access/clog.h index f04eb02a58..3eda52a12a 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/clog.h,v 1.14 2005/08/20 23:26:29 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/clog.h,v 1.15 2005/12/06 23:08:34 tgl Exp $ */ #ifndef CLOG_H #define CLOG_H @@ -28,6 +28,10 @@ typedef int XidStatus; #define TRANSACTION_STATUS_SUB_COMMITTED 0x03 +/* Number of SLRU buffers to use for clog */ +#define NUM_CLOG_BUFFERS 8 + + extern void TransactionIdSetStatus(TransactionId xid, XidStatus status); extern XidStatus TransactionIdGetStatus(TransactionId xid); diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index 02f2d601c5..feee079fd0 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/multixact.h,v 1.7 2005/10/15 02:49:42 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/multixact.h,v 1.8 2005/12/06 23:08:34 tgl Exp $ */ #ifndef MULTIXACT_H #define MULTIXACT_H @@ -18,6 +18,10 @@ #define MultiXactIdIsValid(multi) ((multi) != InvalidMultiXactId) +/* Number of SLRU buffers to use for multixact */ +#define NUM_MXACTOFFSET_BUFFERS 8 +#define NUM_MXACTMEMBER_BUFFERS 16 + /* ---------------- * multixact-related XLOG entries * ---------------- diff --git a/src/include/access/slru.h b/src/include/access/slru.h index 62acb43c4e..66d65c7bed 100644 --- a/src/include/access/slru.h +++ b/src/include/access/slru.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/slru.h,v 1.16 2005/12/06 18:10:06 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/slru.h,v 1.17 2005/12/06 23:08:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,13 +16,6 @@ #include "storage/lwlock.h" -/* - * Number of page buffers. Ideally this could be different for CLOG and - * SUBTRANS, but the benefit doesn't seem to be worth any additional - * notational cruft. - */ -#define NUM_SLRU_BUFFERS 8 - /* * Page status codes. Note that these do not include the "dirty" bit. * page_dirty can be TRUE only in the VALID or WRITE_IN_PROGRESS states; @@ -44,16 +37,19 @@ typedef struct SlruSharedData { LWLockId ControlLock; + /* Number of buffers managed by this SLRU structure */ + int num_slots; + /* - * Info for each buffer slot. Page number is undefined when status is - * EMPTY. + * Arrays holding info for each buffer slot. Page number is undefined + * when status is EMPTY, as is page_lru_count. */ - char *page_buffer[NUM_SLRU_BUFFERS]; - SlruPageStatus page_status[NUM_SLRU_BUFFERS]; - bool page_dirty[NUM_SLRU_BUFFERS]; - int page_number[NUM_SLRU_BUFFERS]; - int page_lru_count[NUM_SLRU_BUFFERS]; - LWLockId buffer_locks[NUM_SLRU_BUFFERS]; + char **page_buffer; + SlruPageStatus *page_status; + bool *page_dirty; + int *page_number; + int *page_lru_count; + LWLockId *buffer_locks; /*---------- * We mark a page "most recently used" by setting @@ -110,8 +106,8 @@ typedef SlruCtlData *SlruCtl; typedef struct SlruFlushData *SlruFlush; -extern Size SimpleLruShmemSize(void); -extern void SimpleLruInit(SlruCtl ctl, const char *name, +extern Size SimpleLruShmemSize(int nslots); +extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, LWLockId ctllock, const char *subdir); extern int SimpleLruZeroPage(SlruCtl ctl, int pageno); extern int SimpleLruReadPage(SlruCtl ctl, int pageno, TransactionId xid); diff --git a/src/include/access/subtrans.h b/src/include/access/subtrans.h index cdd16e90cb..e9f55963c9 100644 --- a/src/include/access/subtrans.h +++ b/src/include/access/subtrans.h @@ -6,11 +6,14 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/subtrans.h,v 1.7 2005/08/20 23:26:29 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/subtrans.h,v 1.8 2005/12/06 23:08:34 tgl Exp $ */ #ifndef SUBTRANS_H #define SUBTRANS_H +/* Number of SLRU buffers to use for subtrans */ +#define NUM_SUBTRANS_BUFFERS 32 + extern void SubTransSetParent(TransactionId xid, TransactionId parent); extern TransactionId SubTransGetParent(TransactionId xid); extern TransactionId SubTransGetTopmostTransaction(TransactionId xid);