Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,432 changes: 1,432 additions & 0 deletions doc/design-shared-buffers-online-resize.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/backend/postmaster/bgwriter.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "postmaster/interrupt.h"
#include "storage/aio_subsys.h"
#include "storage/buf_internals.h"
#include "storage/buf_resize.h"
#include "storage/bufmgr.h"
#include "storage/condition_variable.h"
#include "storage/fd.h"
Expand Down Expand Up @@ -235,6 +236,11 @@ BackgroundWriterMain(const void *startup_data, size_t startup_data_len)
*/
can_hibernate = BgBufferSync(&wb_context);

/*
* Drain any condemned buffers from a buffer pool shrink.
*/
BufPoolDrainCondemnedBuffers();

/* Report pending statistics to the cumulative stats system */
pgstat_report_bgwriter();
pgstat_report_wal(true);
Expand Down
11 changes: 11 additions & 0 deletions src/backend/postmaster/postmaster.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
#include "replication/slotsync.h"
#include "replication/walsender.h"
#include "storage/aio_subsys.h"
#include "storage/buf_resize.h"
#include "storage/fd.h"
#include "storage/io_worker.h"
#include "storage/ipc.h"
Expand Down Expand Up @@ -2014,6 +2015,16 @@ process_pm_reload_request(void)
ereport(LOG,
(errmsg("received SIGHUP, reloading configuration files")));
ProcessConfigFile(PGC_SIGHUP);

/*
* Execute any pending buffer pool resize before notifying children.
* The resize (if any) was requested by assign_shared_buffers() during
* ProcessConfigFile(). We execute it now so that NBuffers is updated
* (via ProcSignalBarrier) in all backends before they process SIGHUP
* and update their SharedBuffersGUC.
*/
ExecuteBufferPoolResize();

SignalChildren(SIGHUP, btmask_all_except(B_DEAD_END_BACKEND));

/* Reload authentication config files too */
Expand Down
1 change: 1 addition & 0 deletions src/backend/storage/buffer/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ include $(top_builddir)/src/Makefile.global

OBJS = \
buf_init.o \
buf_resize.o \
buf_table.o \
bufmgr.o \
freelist.o \
Expand Down
131 changes: 86 additions & 45 deletions src/backend/storage/buffer/buf_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "storage/aio.h"
#include "storage/buf_internals.h"
#include "storage/buf_resize.h"
#include "storage/bufmgr.h"

BufferDescPadded *BufferDescriptors;
Expand Down Expand Up @@ -63,6 +64,16 @@ CkptSortItem *CkptBufferIds;
*
* This is called once during shared-memory initialization (either in the
* postmaster, or in a standalone backend).
*
* When max_shared_buffers is configured, BufferPoolReserveMemory() has
* already set up the global pointers (BufferDescriptors, BufferBlocks, etc.)
* pointing into separately-mapped VA regions. In that case, we skip the
* ShmemInitStruct allocations for the buffer arrays and just initialize
* the descriptors in the pre-allocated memory.
*
* When max_shared_buffers is not configured (the default), we use the
* traditional path of allocating everything from the main shared memory
* segment via ShmemInitStruct.
*/
void
BufferManagerShmemInit(void)
Expand All @@ -71,36 +82,55 @@ BufferManagerShmemInit(void)
foundDescs,
foundIOCV,
foundBufCkpt;
bool using_reserved_memory = (MaxNBuffers > 0 &&
MaxNBuffers > NBuffers);

if (using_reserved_memory)
{
/*
* Memory was already reserved by BufferPoolReserveMemory() and
* global pointers are already set. Mark as "not found" so we
* initialize the descriptors below.
*/
foundDescs = false;
foundBufs = false;
foundIOCV = false;
foundBufCkpt = false;
}
else
{
/* Traditional path: allocate from main shared memory segment */

/* Align descriptors to a cacheline boundary. */
BufferDescriptors = (BufferDescPadded *)
ShmemInitStruct("Buffer Descriptors",
NBuffers * sizeof(BufferDescPadded),
&foundDescs);

/* Align buffer pool on IO page size boundary. */
BufferBlocks = (char *)
TYPEALIGN(PG_IO_ALIGN_SIZE,
ShmemInitStruct("Buffer Blocks",
NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE,
&foundBufs));

/* Align condition variables to cacheline boundary. */
BufferIOCVArray = (ConditionVariableMinimallyPadded *)
ShmemInitStruct("Buffer IO Condition Variables",
NBuffers * sizeof(ConditionVariableMinimallyPadded),
&foundIOCV);

/* Align descriptors to a cacheline boundary. */
BufferDescriptors = (BufferDescPadded *)
ShmemInitStruct("Buffer Descriptors",
NBuffers * sizeof(BufferDescPadded),
&foundDescs);

/* Align buffer pool on IO page size boundary. */
BufferBlocks = (char *)
TYPEALIGN(PG_IO_ALIGN_SIZE,
ShmemInitStruct("Buffer Blocks",
NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE,
&foundBufs));

/* Align condition variables to cacheline boundary. */
BufferIOCVArray = (ConditionVariableMinimallyPadded *)
ShmemInitStruct("Buffer IO Condition Variables",
NBuffers * sizeof(ConditionVariableMinimallyPadded),
&foundIOCV);

/*
* The array used to sort to-be-checkpointed buffer ids is located in
* shared memory, to avoid having to allocate significant amounts of
* memory at runtime. As that'd be in the middle of a checkpoint, or when
* the checkpointer is restarted, memory allocation failures would be
* painful.
*/
CkptBufferIds = (CkptSortItem *)
ShmemInitStruct("Checkpoint BufferIds",
NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
/*
* The array used to sort to-be-checkpointed buffer ids is located in
* shared memory, to avoid having to allocate significant amounts of
* memory at runtime. As that'd be in the middle of a checkpoint, or
* when the checkpointer is restarted, memory allocation failures
* would be painful.
*/
CkptBufferIds = (CkptSortItem *)
ShmemInitStruct("Checkpoint BufferIds",
NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
}

if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
{
Expand Down Expand Up @@ -148,32 +178,43 @@ BufferManagerShmemInit(void)
*
* compute the size of shared memory for the buffer pool including
* data pages, buffer descriptors, hash tables, etc.
*
* When max_shared_buffers is configured for online resize, the buffer
* arrays are allocated separately (not from the main shmem segment),
* so we only include the strategy/hash table sizes here.
*/
Size
BufferManagerShmemSize(void)
{
Size size = 0;
bool using_reserved_memory = (MaxNBuffers > 0 &&
MaxNBuffers > NBuffers);

/* size of buffer descriptors */
size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
/* to allow aligning buffer descriptors */
size = add_size(size, PG_CACHE_LINE_SIZE);
if (!using_reserved_memory)
{
/* Traditional path: everything in main shared memory */

/* size of data pages, plus alignment padding */
size = add_size(size, PG_IO_ALIGN_SIZE);
size = add_size(size, mul_size(NBuffers, BLCKSZ));
/* size of buffer descriptors */
size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
/* to allow aligning buffer descriptors */
size = add_size(size, PG_CACHE_LINE_SIZE);

/* size of stuff controlled by freelist.c */
size = add_size(size, StrategyShmemSize());
/* size of data pages, plus alignment padding */
size = add_size(size, PG_IO_ALIGN_SIZE);
size = add_size(size, mul_size(NBuffers, BLCKSZ));

/* size of I/O condition variables */
size = add_size(size, mul_size(NBuffers,
sizeof(ConditionVariableMinimallyPadded)));
/* to allow aligning the above */
size = add_size(size, PG_CACHE_LINE_SIZE);

/* size of I/O condition variables */
size = add_size(size, mul_size(NBuffers,
sizeof(ConditionVariableMinimallyPadded)));
/* to allow aligning the above */
size = add_size(size, PG_CACHE_LINE_SIZE);
/* size of checkpoint sort array in bufmgr.c */
size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
}

/* size of checkpoint sort array in bufmgr.c */
size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
/* size of stuff controlled by freelist.c (always in main shmem) */
size = add_size(size, StrategyShmemSize());

return size;
}
Loading