提交 dc6d4049 编写于 作者: T Tom Lane

Repair performance problem in SI segment manipulations: iterating

through MAXBACKENDS array entries used to be fine when MAXBACKENDS = 64.
It's not so cool with MAXBACKENDS = 1024 (or more!), especially not in a
frequently-used routine like SIDelExpiredDataEntries.  Repair by making
procState array size be the soft MaxBackends limit rather than the hard
limit, and by converting SIGetProcStateLimit() to a macro.
上级 33c6d609
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.24 1999/05/25 16:11:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.25 1999/05/28 17:03:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -108,7 +108,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends) ...@@ -108,7 +108,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
*/ */
InitProcGlobal(key, maxBackends); InitProcGlobal(key, maxBackends);
CreateSharedInvalidationState(key); CreateSharedInvalidationState(key, maxBackends);
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.14 1999/05/25 16:11:12 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.15 1999/05/28 17:03:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,12 +31,12 @@ extern BackendTag MyBackendTag; ...@@ -31,12 +31,12 @@ extern BackendTag MyBackendTag;
SPINLOCK SInvalLock = (SPINLOCK) NULL; SPINLOCK SInvalLock = (SPINLOCK) NULL;
/****************************************************************************/ /****************************************************************************/
/* CreateSharedInvalidationState(key) Create a buffer segment */ /* CreateSharedInvalidationState() Create a buffer segment */
/* */ /* */
/* should be called only by the POSTMASTER */ /* should be called only by the POSTMASTER */
/****************************************************************************/ /****************************************************************************/
void void
CreateSharedInvalidationState(IPCKey key) CreateSharedInvalidationState(IPCKey key, int maxBackends)
{ {
int status; int status;
...@@ -46,7 +46,8 @@ CreateSharedInvalidationState(IPCKey key) ...@@ -46,7 +46,8 @@ CreateSharedInvalidationState(IPCKey key)
*/ */
/* SInvalLock gets set in spin.c, during spinlock init */ /* SInvalLock gets set in spin.c, during spinlock init */
status = SISegmentInit(true, IPCKeyGetSIBufferMemoryBlock(key)); status = SISegmentInit(true, IPCKeyGetSIBufferMemoryBlock(key),
maxBackends);
if (status == -1) if (status == -1)
elog(FATAL, "CreateSharedInvalidationState: failed segment init"); elog(FATAL, "CreateSharedInvalidationState: failed segment init");
...@@ -64,11 +65,11 @@ AttachSharedInvalidationState(IPCKey key) ...@@ -64,11 +65,11 @@ AttachSharedInvalidationState(IPCKey key)
if (key == PrivateIPCKey) if (key == PrivateIPCKey)
{ {
CreateSharedInvalidationState(key); CreateSharedInvalidationState(key, 16);
return; return;
} }
/* SInvalLock gets set in spin.c, during spinlock init */ /* SInvalLock gets set in spin.c, during spinlock init */
status = SISegmentInit(false, IPCKeyGetSIBufferMemoryBlock(key)); status = SISegmentInit(false, IPCKeyGetSIBufferMemoryBlock(key), 0);
if (status == -1) if (status == -1)
elog(FATAL, "AttachSharedInvalidationState: failed segment init"); elog(FATAL, "AttachSharedInvalidationState: failed segment init");
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.19 1999/05/25 16:11:13 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.20 1999/05/28 17:03:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "storage/backendid.h" #include "storage/backendid.h"
#include "storage/sinvaladt.h" #include "storage/sinvaladt.h"
#include "storage/lmgr.h" #include "storage/lmgr.h"
#include "utils/memutils.h"
#include "utils/palloc.h" #include "utils/palloc.h"
#include "utils/trace.h" #include "utils/trace.h"
...@@ -115,11 +116,9 @@ static BackendId ...@@ -115,11 +116,9 @@ static BackendId
SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag) SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
{ {
Index index; Index index;
ProcState *stateP; ProcState *stateP = NULL;
stateP = NULL; for (index = 0; index < segInOutP->maxBackends; index++)
for (index = 0; index < MAXBACKENDS; index++)
{ {
if (segInOutP->procState[index].tag == InvalidBackendTag || if (segInOutP->procState[index].tag == InvalidBackendTag ||
segInOutP->procState[index].tag == backendTag) segInOutP->procState[index].tag == backendTag)
...@@ -141,7 +140,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag) ...@@ -141,7 +140,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
/* verify that all "procState" entries checked for matching tags */ /* verify that all "procState" entries checked for matching tags */
for (index++; index < MAXBACKENDS; index++) for (index++; index < segInOutP->maxBackends; index++)
{ {
if (segInOutP->procState[index].tag == backendTag) if (segInOutP->procState[index].tag == backendTag)
elog(FATAL, "SIAssignBackendId: tag %d found twice", backendTag); elog(FATAL, "SIAssignBackendId: tag %d found twice", backendTag);
...@@ -201,30 +200,29 @@ CleanupInvalidationState(int status, /* XXX */ ...@@ -201,30 +200,29 @@ CleanupInvalidationState(int status, /* XXX */
/************************************************************************/ /************************************************************************/
/* SIComputeSize() - retuns the size of a buffer segment */ /* SIComputeSize() - compute size and offsets for SI segment */
/************************************************************************/ /************************************************************************/
static SISegOffsets * static void
SIComputeSize(int *segSize) SIComputeSize(SISegOffsets *oP, int maxBackends)
{ {
int A, int A,
B, B,
a, a,
b, b,
totalSize; totalSize;
SISegOffsets *oP;
A = 0; A = 0;
a = SizeSISeg; /* offset to first data entry */ /* sizeof(SISeg) includes the first ProcState entry */
b = SizeOfOneSISegEntry * MAXNUMMESSAGES; a = sizeof(SISeg) + sizeof(ProcState) * (maxBackends - 1);
a = MAXALIGN(a); /* offset to first data entry */
b = sizeof(SISegEntry) * MAXNUMMESSAGES;
B = A + a + b; B = A + a + b;
B = MAXALIGN(B);
totalSize = B - A; totalSize = B - A;
*segSize = totalSize;
oP = (SISegOffsets *) palloc(sizeof(SISegOffsets));
oP->startSegment = A; oP->startSegment = A;
oP->offsetToFirstEntry = a; /* relatiove to A */ oP->offsetToFirstEntry = a; /* relative to A */
oP->offsetToEndOfSegemnt = totalSize; /* relative to A */ oP->offsetToEndOfSegment = totalSize; /* relative to A */
return oP;
} }
...@@ -340,11 +338,9 @@ SISetMaxNumEntries(SISeg *segP, int num) ...@@ -340,11 +338,9 @@ SISetMaxNumEntries(SISeg *segP, int num)
/************************************************************************/ /************************************************************************/
/* SIGetProcStateLimit(segP, i) returns the limit of read messages */ /* SIGetProcStateLimit(segP, i) returns the limit of read messages */
/************************************************************************/ /************************************************************************/
static int
SIGetProcStateLimit(SISeg *segP, int i) #define SIGetProcStateLimit(segP,i) \
{ ((segP)->procState[i].limit)
return segP->procState[i].limit;
}
/************************************************************************/ /************************************************************************/
/* SIIncNumEntries(segP, num) increments the current nuber of entries */ /* SIIncNumEntries(segP, num) increments the current nuber of entries */
...@@ -557,7 +553,7 @@ SIDecProcLimit(SISeg *segP, int num) ...@@ -557,7 +553,7 @@ SIDecProcLimit(SISeg *segP, int num)
{ {
int i; int i;
for (i = 0; i < MAXBACKENDS; i++) for (i = 0; i < segP->maxBackends; i++)
{ {
/* decrement only, if there is a limit > 0 */ /* decrement only, if there is a limit > 0 */
if (segP->procState[i].limit > 0) if (segP->procState[i].limit > 0)
...@@ -614,7 +610,7 @@ SISetProcStateInvalid(SISeg *segP) ...@@ -614,7 +610,7 @@ SISetProcStateInvalid(SISeg *segP)
{ {
int i; int i;
for (i = 0; i < MAXBACKENDS; i++) for (i = 0; i < segP->maxBackends; i++)
{ {
if (segP->procState[i].limit == 0) if (segP->procState[i].limit == 0)
{ {
...@@ -688,7 +684,7 @@ SIDelExpiredDataEntries(SISeg *segP) ...@@ -688,7 +684,7 @@ SIDelExpiredDataEntries(SISeg *segP)
h; h;
min = 9999999; min = 9999999;
for (i = 0; i < MAXBACKENDS; i++) for (i = 0; i < segP->maxBackends; i++)
{ {
h = SIGetProcStateLimit(segP, i); h = SIGetProcStateLimit(segP, i);
if (h >= 0) if (h >= 0)
...@@ -715,24 +711,22 @@ SIDelExpiredDataEntries(SISeg *segP) ...@@ -715,24 +711,22 @@ SIDelExpiredDataEntries(SISeg *segP)
/* SISegInit(segP) - initializes the segment */ /* SISegInit(segP) - initializes the segment */
/************************************************************************/ /************************************************************************/
static void static void
SISegInit(SISeg *segP) SISegInit(SISeg *segP, SISegOffsets *oP, int maxBackends)
{ {
SISegOffsets *oP; int i;
int segSize,
i;
SISegEntry *eP; SISegEntry *eP;
oP = SIComputeSize(&segSize); /* set semaphore ids in the segment */
/* set sempahore ids in the segment */
/* XXX */ /* XXX */
SISetStartEntrySection(segP, oP->offsetToFirstEntry); SISetStartEntrySection(segP, oP->offsetToFirstEntry);
SISetEndEntrySection(segP, oP->offsetToEndOfSegemnt); SISetEndEntrySection(segP, oP->offsetToEndOfSegment);
SISetStartFreeSpace(segP, 0); SISetStartFreeSpace(segP, 0);
SISetStartEntryChain(segP, InvalidOffset); SISetStartEntryChain(segP, InvalidOffset);
SISetEndEntryChain(segP, InvalidOffset); SISetEndEntryChain(segP, InvalidOffset);
SISetNumEntries(segP, 0); SISetNumEntries(segP, 0);
SISetMaxNumEntries(segP, MAXNUMMESSAGES); SISetMaxNumEntries(segP, MAXNUMMESSAGES);
for (i = 0; i < MAXBACKENDS; i++) segP->maxBackends = maxBackends;
for (i = 0; i < segP->maxBackends; i++)
{ {
segP->procState[i].limit = -1; /* no backend active !! */ segP->procState[i].limit = -1; /* no backend active !! */
segP->procState[i].resetState = false; segP->procState[i].resetState = false;
...@@ -753,12 +747,6 @@ SISegInit(SISeg *segP) ...@@ -753,12 +747,6 @@ SISegInit(SISeg *segP)
(MAXNUMMESSAGES - 1) * sizeof(SISegEntry)); (MAXNUMMESSAGES - 1) * sizeof(SISegEntry));
eP->isfree = true; eP->isfree = true;
eP->next = InvalidOffset; /* it's the end of the chain !! */ eP->next = InvalidOffset; /* it's the end of the chain !! */
/*
* Be tidy
*/
pfree(oP);
} }
...@@ -808,13 +796,14 @@ SISegmentAttach(IpcMemoryId shmid) ...@@ -808,13 +796,14 @@ SISegmentAttach(IpcMemoryId shmid)
/************************************************************************/ /************************************************************************/
/* SISegmentInit(killExistingSegment, key) initialize segment */ /* SISegmentInit() initialize SI segment */
/* */
/* NB: maxBackends param is only valid when killExistingSegment is true */
/************************************************************************/ /************************************************************************/
int int
SISegmentInit(bool killExistingSegment, IPCKey key) SISegmentInit(bool killExistingSegment, IPCKey key, int maxBackends)
{ {
SISegOffsets *oP; SISegOffsets offsets;
int segSize;
IpcMemoryId shmId; IpcMemoryId shmId;
bool create; bool create;
...@@ -825,16 +814,9 @@ SISegmentInit(bool killExistingSegment, IPCKey key) ...@@ -825,16 +814,9 @@ SISegmentInit(bool killExistingSegment, IPCKey key)
SISegmentKill(key); SISegmentKill(key);
/* Get a shared segment */ /* Get a shared segment */
SIComputeSize(&offsets, maxBackends);
oP = SIComputeSize(&segSize);
/*
* Be tidy
*/
pfree(oP);
create = true; create = true;
shmId = SISegmentGet(key, segSize, create); shmId = SISegmentGet(key, offsets.offsetToEndOfSegment, create);
if (shmId < 0) if (shmId < 0)
{ {
perror("SISegmentGet: failed"); perror("SISegmentGet: failed");
...@@ -846,7 +828,7 @@ SISegmentInit(bool killExistingSegment, IPCKey key) ...@@ -846,7 +828,7 @@ SISegmentInit(bool killExistingSegment, IPCKey key)
SISegmentAttach(shmId); SISegmentAttach(shmId);
/* Init shared memory table */ /* Init shared memory table */
SISegInit(shmInvalBuffer); SISegInit(shmInvalBuffer, &offsets, maxBackends);
} }
else else
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: sinval.h,v 1.10 1999/02/13 23:22:10 momjian Exp $ * $Id: sinval.h,v 1.11 1999/05/28 17:03:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
extern SPINLOCK SInvalLock; extern SPINLOCK SInvalLock;
extern void CreateSharedInvalidationState(IPCKey key); extern void CreateSharedInvalidationState(IPCKey key, int maxBackends);
extern void AttachSharedInvalidationState(IPCKey key); extern void AttachSharedInvalidationState(IPCKey key);
extern void InitSharedInvalidationState(void); extern void InitSharedInvalidationState(void);
extern void RegisterSharedInvalid(int cacheId, Index hashIndex, extern void RegisterSharedInvalid(int cacheId, Index hashIndex,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: sinvaladt.h,v 1.13 1999/05/25 16:14:46 momjian Exp $ * $Id: sinvaladt.h,v 1.14 1999/05/28 17:03:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,7 +31,8 @@ A------------- Header info -------------- ...@@ -31,7 +31,8 @@ A------------- Header info --------------
endEntryChain (offset relative to B) endEntryChain (offset relative to B)
numEntries numEntries
maxNumEntries maxNumEntries
procState[MAXBACKENDS] --> limit maxBackends
procState[maxBackends] --> limit
resetState (bool) resetState (bool)
a tag (POSTID) a tag (POSTID)
B------------- Start entry section ------- B------------- Start entry section -------
...@@ -70,12 +71,18 @@ typedef struct SISeg ...@@ -70,12 +71,18 @@ typedef struct SISeg
Offset endEntryChain; /* (offset relative to B) */ Offset endEntryChain; /* (offset relative to B) */
int numEntries; int numEntries;
int maxNumEntries; int maxNumEntries;
ProcState procState[MAXBACKENDS]; /* reflects the invalidation state */ int maxBackends; /* size of procState array */
/* here starts the entry section, controlled by offsets */ /*
* We declare procState as 1 entry because C wants a fixed-size array,
* but actually it is maxBackends entries long.
*/
ProcState procState[1]; /* reflects the invalidation state */
/*
* The entry section begins after the end of the procState array.
* Everything there is controlled by offsets.
*/
} SISeg; } SISeg;
#define SizeSISeg sizeof(SISeg)
typedef struct SharedInvalidData typedef struct SharedInvalidData
{ {
int cacheId; /* XXX */ int cacheId; /* XXX */
...@@ -93,13 +100,11 @@ typedef struct SISegEntry ...@@ -93,13 +100,11 @@ typedef struct SISegEntry
Offset next; /* offset to next entry */ Offset next; /* offset to next entry */
} SISegEntry; } SISegEntry;
#define SizeOfOneSISegEntry sizeof(SISegEntry)
typedef struct SISegOffsets typedef struct SISegOffsets
{ {
Offset startSegment; /* always 0 (for now) */ Offset startSegment; /* always 0 (for now) */
Offset offsetToFirstEntry; /* A + a = B */ Offset offsetToFirstEntry; /* A + a = B */
Offset offsetToEndOfSegemnt; /* A + a + b */ Offset offsetToEndOfSegment; /* A + a + b */
} SISegOffsets; } SISegOffsets;
...@@ -118,7 +123,8 @@ extern SISeg *shmInvalBuffer; ...@@ -118,7 +123,8 @@ extern SISeg *shmInvalBuffer;
* prototypes for functions in sinvaladt.c * prototypes for functions in sinvaladt.c
*/ */
extern int SIBackendInit(SISeg *segInOutP); extern int SIBackendInit(SISeg *segInOutP);
extern int SISegmentInit(bool killExistingSegment, IPCKey key); extern int SISegmentInit(bool killExistingSegment, IPCKey key,
int maxBackends);
extern bool SISetDataEntry(SISeg *segP, SharedInvalidData *data); extern bool SISetDataEntry(SISeg *segP, SharedInvalidData *data);
extern void SISetProcStateInvalid(SISeg *segP); extern void SISetProcStateInvalid(SISeg *segP);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册