Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit dc6d404

Browse files
committed
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.
1 parent 33c6d60 commit dc6d404

File tree

5 files changed

+62
-73
lines changed

5 files changed

+62
-73
lines changed

src/backend/storage/ipc/ipci.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.24 1999/05/25 16:11:09 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.25 1999/05/28 17:03:29 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -108,7 +108,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
108108
*/
109109
InitProcGlobal(key, maxBackends);
110110

111-
CreateSharedInvalidationState(key);
111+
CreateSharedInvalidationState(key, maxBackends);
112112
}
113113

114114

src/backend/storage/ipc/sinval.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.14 1999/05/25 16:11:12 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.15 1999/05/28 17:03:29 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -31,12 +31,12 @@ extern BackendTag MyBackendTag;
3131
SPINLOCK SInvalLock = (SPINLOCK) NULL;
3232

3333
/****************************************************************************/
34-
/* CreateSharedInvalidationState(key) Create a buffer segment */
34+
/* CreateSharedInvalidationState() Create a buffer segment */
3535
/* */
3636
/* should be called only by the POSTMASTER */
3737
/****************************************************************************/
3838
void
39-
CreateSharedInvalidationState(IPCKey key)
39+
CreateSharedInvalidationState(IPCKey key, int maxBackends)
4040
{
4141
int status;
4242

@@ -46,7 +46,8 @@ CreateSharedInvalidationState(IPCKey key)
4646
*/
4747

4848
/* SInvalLock gets set in spin.c, during spinlock init */
49-
status = SISegmentInit(true, IPCKeyGetSIBufferMemoryBlock(key));
49+
status = SISegmentInit(true, IPCKeyGetSIBufferMemoryBlock(key),
50+
maxBackends);
5051

5152
if (status == -1)
5253
elog(FATAL, "CreateSharedInvalidationState: failed segment init");
@@ -64,11 +65,11 @@ AttachSharedInvalidationState(IPCKey key)
6465

6566
if (key == PrivateIPCKey)
6667
{
67-
CreateSharedInvalidationState(key);
68+
CreateSharedInvalidationState(key, 16);
6869
return;
6970
}
7071
/* SInvalLock gets set in spin.c, during spinlock init */
71-
status = SISegmentInit(false, IPCKeyGetSIBufferMemoryBlock(key));
72+
status = SISegmentInit(false, IPCKeyGetSIBufferMemoryBlock(key), 0);
7273

7374
if (status == -1)
7475
elog(FATAL, "AttachSharedInvalidationState: failed segment init");

src/backend/storage/ipc/sinvaladt.c

+35-53
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.19 1999/05/25 16:11:13 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.20 1999/05/28 17:03:28 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -21,6 +21,7 @@
2121
#include "storage/backendid.h"
2222
#include "storage/sinvaladt.h"
2323
#include "storage/lmgr.h"
24+
#include "utils/memutils.h"
2425
#include "utils/palloc.h"
2526
#include "utils/trace.h"
2627

@@ -115,11 +116,9 @@ static BackendId
115116
SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
116117
{
117118
Index index;
118-
ProcState *stateP;
119+
ProcState *stateP = NULL;
119120

120-
stateP = NULL;
121-
122-
for (index = 0; index < MAXBACKENDS; index++)
121+
for (index = 0; index < segInOutP->maxBackends; index++)
123122
{
124123
if (segInOutP->procState[index].tag == InvalidBackendTag ||
125124
segInOutP->procState[index].tag == backendTag)
@@ -141,7 +140,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
141140

142141
/* verify that all "procState" entries checked for matching tags */
143142

144-
for (index++; index < MAXBACKENDS; index++)
143+
for (index++; index < segInOutP->maxBackends; index++)
145144
{
146145
if (segInOutP->procState[index].tag == backendTag)
147146
elog(FATAL, "SIAssignBackendId: tag %d found twice", backendTag);
@@ -201,30 +200,29 @@ CleanupInvalidationState(int status, /* XXX */
201200

202201

203202
/************************************************************************/
204-
/* SIComputeSize() - retuns the size of a buffer segment */
203+
/* SIComputeSize() - compute size and offsets for SI segment */
205204
/************************************************************************/
206-
static SISegOffsets *
207-
SIComputeSize(int *segSize)
205+
static void
206+
SIComputeSize(SISegOffsets *oP, int maxBackends)
208207
{
209208
int A,
210209
B,
211210
a,
212211
b,
213212
totalSize;
214-
SISegOffsets *oP;
215213

216214
A = 0;
217-
a = SizeSISeg; /* offset to first data entry */
218-
b = SizeOfOneSISegEntry * MAXNUMMESSAGES;
215+
/* sizeof(SISeg) includes the first ProcState entry */
216+
a = sizeof(SISeg) + sizeof(ProcState) * (maxBackends - 1);
217+
a = MAXALIGN(a); /* offset to first data entry */
218+
b = sizeof(SISegEntry) * MAXNUMMESSAGES;
219219
B = A + a + b;
220+
B = MAXALIGN(B);
220221
totalSize = B - A;
221-
*segSize = totalSize;
222222

223-
oP = (SISegOffsets *) palloc(sizeof(SISegOffsets));
224223
oP->startSegment = A;
225-
oP->offsetToFirstEntry = a; /* relatiove to A */
226-
oP->offsetToEndOfSegemnt = totalSize; /* relative to A */
227-
return oP;
224+
oP->offsetToFirstEntry = a; /* relative to A */
225+
oP->offsetToEndOfSegment = totalSize; /* relative to A */
228226
}
229227

230228

@@ -340,11 +338,9 @@ SISetMaxNumEntries(SISeg *segP, int num)
340338
/************************************************************************/
341339
/* SIGetProcStateLimit(segP, i) returns the limit of read messages */
342340
/************************************************************************/
343-
static int
344-
SIGetProcStateLimit(SISeg *segP, int i)
345-
{
346-
return segP->procState[i].limit;
347-
}
341+
342+
#define SIGetProcStateLimit(segP,i) \
343+
((segP)->procState[i].limit)
348344

349345
/************************************************************************/
350346
/* SIIncNumEntries(segP, num) increments the current nuber of entries */
@@ -557,7 +553,7 @@ SIDecProcLimit(SISeg *segP, int num)
557553
{
558554
int i;
559555

560-
for (i = 0; i < MAXBACKENDS; i++)
556+
for (i = 0; i < segP->maxBackends; i++)
561557
{
562558
/* decrement only, if there is a limit > 0 */
563559
if (segP->procState[i].limit > 0)
@@ -614,7 +610,7 @@ SISetProcStateInvalid(SISeg *segP)
614610
{
615611
int i;
616612

617-
for (i = 0; i < MAXBACKENDS; i++)
613+
for (i = 0; i < segP->maxBackends; i++)
618614
{
619615
if (segP->procState[i].limit == 0)
620616
{
@@ -688,7 +684,7 @@ SIDelExpiredDataEntries(SISeg *segP)
688684
h;
689685

690686
min = 9999999;
691-
for (i = 0; i < MAXBACKENDS; i++)
687+
for (i = 0; i < segP->maxBackends; i++)
692688
{
693689
h = SIGetProcStateLimit(segP, i);
694690
if (h >= 0)
@@ -715,24 +711,22 @@ SIDelExpiredDataEntries(SISeg *segP)
715711
/* SISegInit(segP) - initializes the segment */
716712
/************************************************************************/
717713
static void
718-
SISegInit(SISeg *segP)
714+
SISegInit(SISeg *segP, SISegOffsets *oP, int maxBackends)
719715
{
720-
SISegOffsets *oP;
721-
int segSize,
722-
i;
716+
int i;
723717
SISegEntry *eP;
724718

725-
oP = SIComputeSize(&segSize);
726-
/* set sempahore ids in the segment */
719+
/* set semaphore ids in the segment */
727720
/* XXX */
728721
SISetStartEntrySection(segP, oP->offsetToFirstEntry);
729-
SISetEndEntrySection(segP, oP->offsetToEndOfSegemnt);
722+
SISetEndEntrySection(segP, oP->offsetToEndOfSegment);
730723
SISetStartFreeSpace(segP, 0);
731724
SISetStartEntryChain(segP, InvalidOffset);
732725
SISetEndEntryChain(segP, InvalidOffset);
733726
SISetNumEntries(segP, 0);
734727
SISetMaxNumEntries(segP, MAXNUMMESSAGES);
735-
for (i = 0; i < MAXBACKENDS; i++)
728+
segP->maxBackends = maxBackends;
729+
for (i = 0; i < segP->maxBackends; i++)
736730
{
737731
segP->procState[i].limit = -1; /* no backend active !! */
738732
segP->procState[i].resetState = false;
@@ -753,12 +747,6 @@ SISegInit(SISeg *segP)
753747
(MAXNUMMESSAGES - 1) * sizeof(SISegEntry));
754748
eP->isfree = true;
755749
eP->next = InvalidOffset; /* it's the end of the chain !! */
756-
757-
/*
758-
* Be tidy
759-
*/
760-
pfree(oP);
761-
762750
}
763751

764752

@@ -808,13 +796,14 @@ SISegmentAttach(IpcMemoryId shmid)
808796

809797

810798
/************************************************************************/
811-
/* SISegmentInit(killExistingSegment, key) initialize segment */
799+
/* SISegmentInit() initialize SI segment */
800+
/* */
801+
/* NB: maxBackends param is only valid when killExistingSegment is true */
812802
/************************************************************************/
813803
int
814-
SISegmentInit(bool killExistingSegment, IPCKey key)
804+
SISegmentInit(bool killExistingSegment, IPCKey key, int maxBackends)
815805
{
816-
SISegOffsets *oP;
817-
int segSize;
806+
SISegOffsets offsets;
818807
IpcMemoryId shmId;
819808
bool create;
820809

@@ -825,16 +814,9 @@ SISegmentInit(bool killExistingSegment, IPCKey key)
825814
SISegmentKill(key);
826815

827816
/* Get a shared segment */
828-
829-
oP = SIComputeSize(&segSize);
830-
831-
/*
832-
* Be tidy
833-
*/
834-
pfree(oP);
835-
817+
SIComputeSize(&offsets, maxBackends);
836818
create = true;
837-
shmId = SISegmentGet(key, segSize, create);
819+
shmId = SISegmentGet(key, offsets.offsetToEndOfSegment, create);
838820
if (shmId < 0)
839821
{
840822
perror("SISegmentGet: failed");
@@ -846,7 +828,7 @@ SISegmentInit(bool killExistingSegment, IPCKey key)
846828
SISegmentAttach(shmId);
847829

848830
/* Init shared memory table */
849-
SISegInit(shmInvalBuffer);
831+
SISegInit(shmInvalBuffer, &offsets, maxBackends);
850832
}
851833
else
852834
{

src/include/storage/sinval.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: sinval.h,v 1.10 1999/02/13 23:22:10 momjian Exp $
9+
* $Id: sinval.h,v 1.11 1999/05/28 17:03:31 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -18,7 +18,7 @@
1818

1919
extern SPINLOCK SInvalLock;
2020

21-
extern void CreateSharedInvalidationState(IPCKey key);
21+
extern void CreateSharedInvalidationState(IPCKey key, int maxBackends);
2222
extern void AttachSharedInvalidationState(IPCKey key);
2323
extern void InitSharedInvalidationState(void);
2424
extern void RegisterSharedInvalid(int cacheId, Index hashIndex,

src/include/storage/sinvaladt.h

+16-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: sinvaladt.h,v 1.13 1999/05/25 16:14:46 momjian Exp $
9+
* $Id: sinvaladt.h,v 1.14 1999/05/28 17:03:30 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -31,7 +31,8 @@ A------------- Header info --------------
3131
endEntryChain (offset relative to B)
3232
numEntries
3333
maxNumEntries
34-
procState[MAXBACKENDS] --> limit
34+
maxBackends
35+
procState[maxBackends] --> limit
3536
resetState (bool)
3637
a tag (POSTID)
3738
B------------- Start entry section -------
@@ -70,12 +71,18 @@ typedef struct SISeg
7071
Offset endEntryChain; /* (offset relative to B) */
7172
int numEntries;
7273
int maxNumEntries;
73-
ProcState procState[MAXBACKENDS]; /* reflects the invalidation state */
74-
/* here starts the entry section, controlled by offsets */
74+
int maxBackends; /* size of procState array */
75+
/*
76+
* We declare procState as 1 entry because C wants a fixed-size array,
77+
* but actually it is maxBackends entries long.
78+
*/
79+
ProcState procState[1]; /* reflects the invalidation state */
80+
/*
81+
* The entry section begins after the end of the procState array.
82+
* Everything there is controlled by offsets.
83+
*/
7584
} SISeg;
7685

77-
#define SizeSISeg sizeof(SISeg)
78-
7986
typedef struct SharedInvalidData
8087
{
8188
int cacheId; /* XXX */
@@ -93,13 +100,11 @@ typedef struct SISegEntry
93100
Offset next; /* offset to next entry */
94101
} SISegEntry;
95102

96-
#define SizeOfOneSISegEntry sizeof(SISegEntry)
97-
98103
typedef struct SISegOffsets
99104
{
100105
Offset startSegment; /* always 0 (for now) */
101106
Offset offsetToFirstEntry; /* A + a = B */
102-
Offset offsetToEndOfSegemnt; /* A + a + b */
107+
Offset offsetToEndOfSegment; /* A + a + b */
103108
} SISegOffsets;
104109

105110

@@ -118,7 +123,8 @@ extern SISeg *shmInvalBuffer;
118123
* prototypes for functions in sinvaladt.c
119124
*/
120125
extern int SIBackendInit(SISeg *segInOutP);
121-
extern int SISegmentInit(bool killExistingSegment, IPCKey key);
126+
extern int SISegmentInit(bool killExistingSegment, IPCKey key,
127+
int maxBackends);
122128

123129
extern bool SISetDataEntry(SISeg *segP, SharedInvalidData *data);
124130
extern void SISetProcStateInvalid(SISeg *segP);

0 commit comments

Comments
 (0)