diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-06-19 21:32:56 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-06-19 21:32:56 +0000 |
commit | fad153ec45299bd4d4f29dec8d9e04e2f1c08148 (patch) | |
tree | 9a1335bb5b2fe5bbe9d1b4d405c8da03d004afc4 /src/backend/utils/cache/inval.c | |
parent | 30dc388a0dd9ceca911b101fe1877cf7a23776fa (diff) |
Rewrite the sinval messaging mechanism to reduce contention and avoid
unnecessary cache resets. The major changes are:
* When the queue overflows, we only issue a cache reset to the specific
backend or backends that still haven't read the oldest message, rather
than resetting everyone as in the original coding.
* When we observe backend(s) falling well behind, we signal SIGUSR1
to only one backend, the one that is furthest behind and doesn't already
have a signal outstanding for it. When it finishes catching up, it will
in turn signal SIGUSR1 to the next-furthest-back guy, if there is one that
is far enough behind to justify a signal. The PMSIGNAL_WAKEN_CHILDREN
mechanism is removed.
* We don't attempt to clean out dead messages after every message-receipt
operation; rather, we do it on the insertion side, and only when the queue
fullness passes certain thresholds.
* Split SInvalLock into SInvalReadLock and SInvalWriteLock so that readers
don't block writers nor vice versa (except during the infrequent queue
cleanout operations).
* Transfer multiple sinval messages for each acquisition of a read or
write lock.
Diffstat (limited to 'src/backend/utils/cache/inval.c')
-rw-r--r-- | src/backend/utils/cache/inval.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c index 50e27923566..050d7cc88de 100644 --- a/src/backend/utils/cache/inval.c +++ b/src/backend/utils/cache/inval.c @@ -80,7 +80,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.85 2008/06/19 00:46:05 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.86 2008/06/19 21:32:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -203,7 +203,7 @@ AddInvalidationMessage(InvalidationChunk **listHdr, if (chunk == NULL) { /* First time through; create initial chunk */ -#define FIRSTCHUNKSIZE 16 +#define FIRSTCHUNKSIZE 32 chunk = (InvalidationChunk *) MemoryContextAlloc(CurTransactionContext, sizeof(InvalidationChunk) + @@ -275,6 +275,23 @@ AppendInvalidationMessageList(InvalidationChunk **destHdr, } \ } while (0) +/* + * Process a list of invalidation messages group-wise. + * + * As above, but the code fragment can handle an array of messages. + * The fragment should refer to the messages as msgs[], with n entries. + */ +#define ProcessMessageListMulti(listHdr, codeFragment) \ + do { \ + InvalidationChunk *_chunk; \ + for (_chunk = (listHdr); _chunk != NULL; _chunk = _chunk->next) \ + { \ + SharedInvalidationMessage *msgs = _chunk->msgs; \ + int n = _chunk->nitems; \ + codeFragment; \ + } \ + } while (0) + /* ---------------------------------------------------------------- * Invalidation set support functions @@ -371,6 +388,18 @@ ProcessInvalidationMessages(InvalidationListHeader *hdr, ProcessMessageList(hdr->rclist, func(msg)); } +/* + * As above, but the function is able to process an array of messages + * rather than just one at a time. + */ +static void +ProcessInvalidationMessagesMulti(InvalidationListHeader *hdr, + void (*func) (const SharedInvalidationMessage *msgs, int n)) +{ + ProcessMessageListMulti(hdr->cclist, func(msgs, n)); + ProcessMessageListMulti(hdr->rclist, func(msgs, n)); +} + /* ---------------------------------------------------------------- * private support functions * ---------------------------------------------------------------- @@ -792,7 +821,7 @@ inval_twophase_postcommit(TransactionId xid, uint16 info, case TWOPHASE_INFO_MSG: msg = (SharedInvalidationMessage *) recdata; Assert(len == sizeof(SharedInvalidationMessage)); - SendSharedInvalidMessage(msg); + SendSharedInvalidMessages(msg, 1); break; case TWOPHASE_INFO_FILE_BEFORE: RelationCacheInitFileInvalidate(true); @@ -850,8 +879,8 @@ AtEOXact_Inval(bool isCommit) AppendInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs, &transInvalInfo->CurrentCmdInvalidMsgs); - ProcessInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs, - SendSharedInvalidMessage); + ProcessInvalidationMessagesMulti(&transInvalInfo->PriorCmdInvalidMsgs, + SendSharedInvalidMessages); if (transInvalInfo->RelcacheInitFileInval) RelationCacheInitFileInvalidate(false); @@ -1033,8 +1062,8 @@ EndNonTransactionalInvalidation(void) /* Send out the invals */ ProcessInvalidationMessages(&transInvalInfo->CurrentCmdInvalidMsgs, LocalExecuteInvalidationMessage); - ProcessInvalidationMessages(&transInvalInfo->CurrentCmdInvalidMsgs, - SendSharedInvalidMessage); + ProcessInvalidationMessagesMulti(&transInvalInfo->CurrentCmdInvalidMsgs, + SendSharedInvalidMessages); /* Clean up and release memory */ for (chunk = transInvalInfo->CurrentCmdInvalidMsgs.cclist; |