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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 7 additions & 6 deletions
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

Lines changed: 35 additions & 53 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 16 additions & 10 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy