Skip to content

Commit a5fc360

Browse files
erthalionCommitfest Bot
authored andcommitted
Introduce multiple shmem segments for shared buffers
Add more shmem segments to split shared buffers into following chunks: * BUFFERS_SHMEM_SEGMENT: contains buffer blocks * BUFFER_DESCRIPTORS_SHMEM_SEGMENT: contains buffer descriptors * BUFFER_IOCV_SHMEM_SEGMENT: contains condition variables for buffers * CHECKPOINT_BUFFERS_SHMEM_SEGMENT: contains checkpoint buffer ids * STRATEGY_SHMEM_SEGMENT: contains buffer strategy status Size of the corresponding shared data directly depends on NBuffers, meaning that if we would like to change NBuffers, they have to be resized correspondingly. Placing each of them in a separate shmem segment allows to achieve that. There are some asumptions made about each of shmem segments upper size limit. The buffer blocks have the largest, while the rest claim less extra room for resize. Ideally those limits have to be deduced from the maximum allowed shared memory.
1 parent 1a9817c commit a5fc360

File tree

7 files changed

+105
-37
lines changed

7 files changed

+105
-37
lines changed

src/backend/port/sysv_shmem.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,18 @@ static int next_free_segment = 0;
139139
*
140140
* The reserved space for each segment is calculated as a fraction of the total
141141
* reserved space (MaxAvailableMemory), as specified in the SHMEM_RESIZE_RATIO
142-
* array.
142+
* array. E.g. we allow BUFFERS_SHMEM_SEGMENT to take up to 60% of the whole
143+
* space when resizing, based on the fact that it most likely will be the main
144+
* consumer of this memory. Those numbers are pulled out of thin air for now,
145+
* makes sense to evaluate them more precise.
143146
*/
144-
static double SHMEM_RESIZE_RATIO[1] = {
145-
1.0, /* MAIN_SHMEM_SLOT */
147+
static double SHMEM_RESIZE_RATIO[6] = {
148+
0.1, /* MAIN_SHMEM_SEGMENT */
149+
0.6, /* BUFFERS_SHMEM_SEGMENT */
150+
0.1, /* BUFFER_DESCRIPTORS_SHMEM_SEGMENT */
151+
0.1, /* BUFFER_IOCV_SHMEM_SEGMENT */
152+
0.05, /* CHECKPOINT_BUFFERS_SHMEM_SEGMENT */
153+
0.05, /* STRATEGY_SHMEM_SEGMENT */
146154
};
147155

148156
/*
@@ -167,6 +175,16 @@ MappingName(int shmem_segment)
167175
{
168176
case MAIN_SHMEM_SEGMENT:
169177
return "main";
178+
case BUFFERS_SHMEM_SEGMENT:
179+
return "buffers";
180+
case BUFFER_DESCRIPTORS_SHMEM_SEGMENT:
181+
return "descriptors";
182+
case BUFFER_IOCV_SHMEM_SEGMENT:
183+
return "iocv";
184+
case CHECKPOINT_BUFFERS_SHMEM_SEGMENT:
185+
return "checkpoint";
186+
case STRATEGY_SHMEM_SEGMENT:
187+
return "strategy";
170188
default:
171189
return "unknown";
172190
}

src/backend/storage/buffer/buf_init.c

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ CkptSortItem *CkptBufferIds;
6262
* Initialize shared buffer pool
6363
*
6464
* This is called once during shared-memory initialization (either in the
65-
* postmaster, or in a standalone backend).
65+
* postmaster, or in a standalone backend). Size of data structures initialized
66+
* here depends on NBuffers, and to be able to change NBuffers without a
67+
* restart we store each structure into a separate shared memory segment, which
68+
* could be resized on demand.
6669
*/
6770
void
6871
BufferManagerShmemInit(void)
@@ -74,22 +77,22 @@ BufferManagerShmemInit(void)
7477

7578
/* Align descriptors to a cacheline boundary. */
7679
BufferDescriptors = (BufferDescPadded *)
77-
ShmemInitStruct("Buffer Descriptors",
80+
ShmemInitStructInSegment("Buffer Descriptors",
7881
NBuffers * sizeof(BufferDescPadded),
79-
&foundDescs);
82+
&foundDescs, BUFFER_DESCRIPTORS_SHMEM_SEGMENT);
8083

8184
/* Align buffer pool on IO page size boundary. */
8285
BufferBlocks = (char *)
8386
TYPEALIGN(PG_IO_ALIGN_SIZE,
84-
ShmemInitStruct("Buffer Blocks",
87+
ShmemInitStructInSegment("Buffer Blocks",
8588
NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE,
86-
&foundBufs));
89+
&foundBufs, BUFFERS_SHMEM_SEGMENT));
8790

8891
/* Align condition variables to cacheline boundary. */
8992
BufferIOCVArray = (ConditionVariableMinimallyPadded *)
90-
ShmemInitStruct("Buffer IO Condition Variables",
93+
ShmemInitStructInSegment("Buffer IO Condition Variables",
9194
NBuffers * sizeof(ConditionVariableMinimallyPadded),
92-
&foundIOCV);
95+
&foundIOCV, BUFFER_IOCV_SHMEM_SEGMENT);
9396

9497
/*
9598
* The array used to sort to-be-checkpointed buffer ids is located in
@@ -99,8 +102,9 @@ BufferManagerShmemInit(void)
99102
* painful.
100103
*/
101104
CkptBufferIds = (CkptSortItem *)
102-
ShmemInitStruct("Checkpoint BufferIds",
103-
NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
105+
ShmemInitStructInSegment("Checkpoint BufferIds",
106+
NBuffers * sizeof(CkptSortItem), &foundBufCkpt,
107+
CHECKPOINT_BUFFERS_SHMEM_SEGMENT);
104108

105109
if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
106110
{
@@ -147,33 +151,54 @@ BufferManagerShmemInit(void)
147151
* BufferManagerShmemSize
148152
*
149153
* compute the size of shared memory for the buffer pool including
150-
* data pages, buffer descriptors, hash tables, etc.
154+
* data pages, buffer descriptors, hash tables, etc. based on the
155+
* shared memory segment. The main segment must not allocate anything
156+
* related to buffers, every other segment will receive part of the
157+
* data.
151158
*/
152159
Size
153-
BufferManagerShmemSize(void)
160+
BufferManagerShmemSize(int shmem_segment)
154161
{
155162
Size size = 0;
156163

157-
/* size of buffer descriptors */
158-
size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
159-
/* to allow aligning buffer descriptors */
160-
size = add_size(size, PG_CACHE_LINE_SIZE);
164+
if (shmem_segment == MAIN_SHMEM_SEGMENT)
165+
return size;
161166

162-
/* size of data pages, plus alignment padding */
163-
size = add_size(size, PG_IO_ALIGN_SIZE);
164-
size = add_size(size, mul_size(NBuffers, BLCKSZ));
167+
if (shmem_segment == BUFFER_DESCRIPTORS_SHMEM_SEGMENT)
168+
{
169+
/* size of buffer descriptors */
170+
size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
171+
/* to allow aligning buffer descriptors */
172+
size = add_size(size, PG_CACHE_LINE_SIZE);
173+
}
165174

166-
/* size of stuff controlled by freelist.c */
167-
size = add_size(size, StrategyShmemSize());
175+
if (shmem_segment == BUFFERS_SHMEM_SEGMENT)
176+
{
177+
/* size of data pages, plus alignment padding */
178+
size = add_size(size, PG_IO_ALIGN_SIZE);
179+
size = add_size(size, mul_size(NBuffers, BLCKSZ));
180+
}
168181

169-
/* size of I/O condition variables */
170-
size = add_size(size, mul_size(NBuffers,
171-
sizeof(ConditionVariableMinimallyPadded)));
172-
/* to allow aligning the above */
173-
size = add_size(size, PG_CACHE_LINE_SIZE);
182+
if (shmem_segment == STRATEGY_SHMEM_SEGMENT)
183+
{
184+
/* size of stuff controlled by freelist.c */
185+
size = add_size(size, StrategyShmemSize());
186+
}
174187

175-
/* size of checkpoint sort array in bufmgr.c */
176-
size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
188+
if (shmem_segment == BUFFER_IOCV_SHMEM_SEGMENT)
189+
{
190+
/* size of I/O condition variables */
191+
size = add_size(size, mul_size(NBuffers,
192+
sizeof(ConditionVariableMinimallyPadded)));
193+
/* to allow aligning the above */
194+
size = add_size(size, PG_CACHE_LINE_SIZE);
195+
}
196+
197+
if (shmem_segment == CHECKPOINT_BUFFERS_SHMEM_SEGMENT)
198+
{
199+
/* size of checkpoint sort array in bufmgr.c */
200+
size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
201+
}
177202

178203
return size;
179204
}

src/backend/storage/buffer/buf_table.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "funcapi.h"
2626
#include "storage/buf_internals.h"
2727
#include "storage/lwlock.h"
28+
#include "storage/pg_shmem.h"
2829
#include "utils/rel.h"
2930
#include "utils/builtins.h"
3031

@@ -64,10 +65,11 @@ InitBufTable(int size)
6465
info.entrysize = sizeof(BufferLookupEnt);
6566
info.num_partitions = NUM_BUFFER_PARTITIONS;
6667

67-
SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
68+
SharedBufHash = ShmemInitHashInSegment("Shared Buffer Lookup Table",
6869
size, size,
6970
&info,
70-
HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE);
71+
HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE,
72+
STRATEGY_SHMEM_SEGMENT);
7173
}
7274

7375
/*

src/backend/storage/buffer/freelist.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "port/atomics.h"
2020
#include "storage/buf_internals.h"
2121
#include "storage/bufmgr.h"
22+
#include "storage/pg_shmem.h"
2223
#include "storage/proc.h"
2324

2425
#define INT_ACCESS_ONCE(var) ((int)(*((volatile int *)&(var))))
@@ -381,9 +382,9 @@ StrategyInitialize(bool init)
381382
* Get or create the shared strategy control block
382383
*/
383384
StrategyControl = (BufferStrategyControl *)
384-
ShmemInitStruct("Buffer Strategy Status",
385+
ShmemInitStructInSegment("Buffer Strategy Status",
385386
sizeof(BufferStrategyControl),
386-
&found);
387+
&found, STRATEGY_SHMEM_SEGMENT);
387388

388389
if (!found)
389390
{

src/backend/storage/ipc/ipci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ CalculateShmemSize(int *num_semaphores, int shmem_segment)
113113
sizeof(ShmemIndexEnt)));
114114
size = add_size(size, dsm_estimate_size());
115115
size = add_size(size, DSMRegistryShmemSize());
116-
size = add_size(size, BufferManagerShmemSize());
116+
size = add_size(size, BufferManagerShmemSize(shmem_segment));
117117
size = add_size(size, LockManagerShmemSize());
118118
size = add_size(size, PredicateLockShmemSize());
119119
size = add_size(size, ProcGlobalShmemSize());

src/include/storage/bufmgr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ extern void EvictRelUnpinnedBuffers(Relation rel,
318318

319319
/* in buf_init.c */
320320
extern void BufferManagerShmemInit(void);
321-
extern Size BufferManagerShmemSize(void);
321+
extern Size BufferManagerShmemSize(int);
322322

323323
/* in localbuf.c */
324324
extern void AtProcExit_LocalBuffers(void);

src/include/storage/pg_shmem.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ typedef struct ShmemSegment
5252
} ShmemSegment;
5353

5454
/* Number of available segments for anonymous memory mappings */
55-
#define ANON_MAPPINGS 1
55+
#define ANON_MAPPINGS 6
5656

5757
extern PGDLLIMPORT ShmemSegment Segments[ANON_MAPPINGS];
5858

@@ -109,7 +109,29 @@ extern void GetHugePageSize(Size *hugepagesize, int *mmap_flags,
109109
int *memfd_flags);
110110
void PrepareHugePages(void);
111111

112+
/*
113+
* To be able to dynamically resize largest parts of the data stored in shared
114+
* memory, we split it into multiple shared memory mappings segments. Each
115+
* segment contains only certain part of the data, which size depends on
116+
* NBuffers.
117+
*/
118+
112119
/* The main segment, contains everything except buffer blocks and related data. */
113120
#define MAIN_SHMEM_SEGMENT 0
114121

122+
/* Buffer blocks */
123+
#define BUFFERS_SHMEM_SEGMENT 1
124+
125+
/* Buffer descriptors */
126+
#define BUFFER_DESCRIPTORS_SHMEM_SEGMENT 2
127+
128+
/* Condition variables for buffers */
129+
#define BUFFER_IOCV_SHMEM_SEGMENT 3
130+
131+
/* Checkpoint BufferIds */
132+
#define CHECKPOINT_BUFFERS_SHMEM_SEGMENT 4
133+
134+
/* Buffer strategy status */
135+
#define STRATEGY_SHMEM_SEGMENT 5
136+
115137
#endif /* PG_SHMEM_H */

0 commit comments

Comments
 (0)