From e2345206dacec8b4454c3b429d0cfac01d5a0a58 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 30 Aug 2021 16:24:59 +0900 Subject: [PATCH] Add shared_memory_size GUC --- src/include/storage/ipc.h | 1 + src/backend/postmaster/postmaster.c | 60 +++++++----- src/backend/storage/ipc/ipci.c | 142 ++++++++++++++++------------ src/backend/utils/misc/guc.c | 13 +++ 4 files changed, 135 insertions(+), 81 deletions(-) diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index 753a6dd4d7..80e191d407 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -77,6 +77,7 @@ extern void check_on_shmem_exit_lists_are_empty(void); /* ipci.c */ extern PGDLLIMPORT shmem_startup_hook_type shmem_startup_hook; +extern Size CalculateShmemSize(int *num_semaphores); extern void CreateSharedMemoryAndSemaphores(void); #endif /* IPC_H */ diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 9c2c98614a..0d3b4b1be0 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -893,6 +893,44 @@ PostmasterMain(int argc, char *argv[]) if (!SelectConfigFiles(userDoption, progname)) ExitPostmaster(2); + /* Verify that DataDir looks reasonable */ + checkDataDir(); + + /* Check that pg_control exists */ + checkControlFile(); + + /* And switch working directory into it */ + ChangeToDataDir(); + + /* + * Register the apply launcher. Since it registers a background worker, + * it needs to be called before InitializeMaxBackends(), and it's probably + * a good idea to call it before any modules had chance to take the + * background worker slots. + */ + ApplyLauncherRegister(); + + /* + * Process any libraries that should be preloaded at postmaster start. + * Thie happens before running -C, so as it is possible to get an + * estimation of the total shared memory size allocated to this system, + * accounting for the portion from loaded libraries. + */ + process_shared_preload_libraries(); + + /* XXX: this should be moved around */ + { + char buf[64]; + Size size; + + size = CalculateShmemSize(NULL); + size += (1024 * 1024) - 1; + size /= (1024 * 1024); + + sprintf(buf, "%lu MB", size); + SetConfigOption("shared_memory_size", buf, PGC_INTERNAL, PGC_S_OVERRIDE); + } + if (output_config_variable != NULL) { /* @@ -907,15 +945,6 @@ PostmasterMain(int argc, char *argv[]) ExitPostmaster(0); } - /* Verify that DataDir looks reasonable */ - checkDataDir(); - - /* Check that pg_control exists */ - checkControlFile(); - - /* And switch working directory into it */ - ChangeToDataDir(); - /* * Check for invalid combinations of GUC settings. */ @@ -996,19 +1025,6 @@ PostmasterMain(int argc, char *argv[]) */ LocalProcessControlFile(false); - /* - * Register the apply launcher. Since it registers a background worker, - * it needs to be called before InitializeMaxBackends(), and it's probably - * a good idea to call it before any modules had chance to take the - * background worker slots. - */ - ApplyLauncherRegister(); - - /* - * process any libraries that should be preloaded at postmaster start - */ - process_shared_preload_libraries(); - /* * Initialize SSL library, if specified. */ diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 3e4ec53a97..b225b1ee70 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -75,6 +75,87 @@ RequestAddinShmemSpace(Size size) total_addin_request = add_size(total_addin_request, size); } +/* + * CalculateShmemSize + * Calculates the amount of shared memory and number of semaphores needed. + * + * If num_semaphores is not NULL, it will be set to the number of semaphores + * required. + * + * Note that this function freezes the additional shared memory request size + * from loadable modules. + */ +Size +CalculateShmemSize(int *num_semaphores) +{ + Size size; + int numSemas; + + /* Compute number of semaphores we'll need */ + numSemas = ProcGlobalSemas(); + numSemas += SpinlockSemas(); + + /* Return the number of semaphores if requested by the caller */ + if (num_semaphores) + *num_semaphores = numSemas; + + /* + * Size of the Postgres shared-memory block is estimated via moderately- + * accurate estimates for the big hogs, plus 100K for the stuff that's too + * small to bother with estimating. + * + * We take some care to ensure that the total size request doesn't overflow + * size_t. If this gets through, we don't need to be so careful during the + * actual allocation phase. + */ + size = 100000; + size = add_size(size, PGSemaphoreShmemSize(numSemas)); + size = add_size(size, SpinlockSemaSize()); + size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE, + sizeof(ShmemIndexEnt))); + size = add_size(size, dsm_estimate_size()); + size = add_size(size, BufferShmemSize()); + size = add_size(size, LockShmemSize()); + size = add_size(size, PredicateLockShmemSize()); + size = add_size(size, ProcGlobalShmemSize()); + size = add_size(size, XLOGShmemSize()); + size = add_size(size, CLOGShmemSize()); + size = add_size(size, CommitTsShmemSize()); + size = add_size(size, SUBTRANSShmemSize()); + size = add_size(size, TwoPhaseShmemSize()); + size = add_size(size, BackgroundWorkerShmemSize()); + size = add_size(size, MultiXactShmemSize()); + size = add_size(size, LWLockShmemSize()); + size = add_size(size, ProcArrayShmemSize()); + size = add_size(size, BackendStatusShmemSize()); + size = add_size(size, SInvalShmemSize()); + size = add_size(size, PMSignalShmemSize()); + size = add_size(size, ProcSignalShmemSize()); + size = add_size(size, CheckpointerShmemSize()); + size = add_size(size, AutoVacuumShmemSize()); + size = add_size(size, ReplicationSlotsShmemSize()); + size = add_size(size, ReplicationOriginShmemSize()); + size = add_size(size, WalSndShmemSize()); + size = add_size(size, WalRcvShmemSize()); + size = add_size(size, PgArchShmemSize()); + size = add_size(size, ApplyLauncherShmemSize()); + size = add_size(size, SnapMgrShmemSize()); + size = add_size(size, BTreeShmemSize()); + size = add_size(size, SyncScanShmemSize()); + size = add_size(size, AsyncShmemSize()); +#ifdef EXEC_BACKEND + size = add_size(size, ShmemBackendArraySize()); +#endif + + /* freeze the addin request size and include it */ + addin_request_allowed = false; + size = add_size(size, total_addin_request); + + /* might as well round it off to a multiple of a typical page size */ + size = add_size(size, 8192 - (size % 8192)); + + return size; +} /* * CreateSharedMemoryAndSemaphores @@ -102,65 +183,8 @@ CreateSharedMemoryAndSemaphores(void) Size size; int numSemas; - /* Compute number of semaphores we'll need */ - numSemas = ProcGlobalSemas(); - numSemas += SpinlockSemas(); - - /* - * Size of the Postgres shared-memory block is estimated via - * moderately-accurate estimates for the big hogs, plus 100K for the - * stuff that's too small to bother with estimating. - * - * We take some care during this phase to ensure that the total size - * request doesn't overflow size_t. If this gets through, we don't - * need to be so careful during the actual allocation phase. - */ - size = 100000; - size = add_size(size, PGSemaphoreShmemSize(numSemas)); - size = add_size(size, SpinlockSemaSize()); - size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE, - sizeof(ShmemIndexEnt))); - size = add_size(size, dsm_estimate_size()); - size = add_size(size, BufferShmemSize()); - size = add_size(size, LockShmemSize()); - size = add_size(size, PredicateLockShmemSize()); - size = add_size(size, ProcGlobalShmemSize()); - size = add_size(size, XLOGShmemSize()); - size = add_size(size, CLOGShmemSize()); - size = add_size(size, CommitTsShmemSize()); - size = add_size(size, SUBTRANSShmemSize()); - size = add_size(size, TwoPhaseShmemSize()); - size = add_size(size, BackgroundWorkerShmemSize()); - size = add_size(size, MultiXactShmemSize()); - size = add_size(size, LWLockShmemSize()); - size = add_size(size, ProcArrayShmemSize()); - size = add_size(size, BackendStatusShmemSize()); - size = add_size(size, SInvalShmemSize()); - size = add_size(size, PMSignalShmemSize()); - size = add_size(size, ProcSignalShmemSize()); - size = add_size(size, CheckpointerShmemSize()); - size = add_size(size, AutoVacuumShmemSize()); - size = add_size(size, ReplicationSlotsShmemSize()); - size = add_size(size, ReplicationOriginShmemSize()); - size = add_size(size, WalSndShmemSize()); - size = add_size(size, WalRcvShmemSize()); - size = add_size(size, PgArchShmemSize()); - size = add_size(size, ApplyLauncherShmemSize()); - size = add_size(size, SnapMgrShmemSize()); - size = add_size(size, BTreeShmemSize()); - size = add_size(size, SyncScanShmemSize()); - size = add_size(size, AsyncShmemSize()); -#ifdef EXEC_BACKEND - size = add_size(size, ShmemBackendArraySize()); -#endif - - /* freeze the addin request size and include it */ - addin_request_allowed = false; - size = add_size(size, total_addin_request); - - /* might as well round it off to a multiple of a typical page size */ - size = add_size(size, 8192 - (size % 8192)); - + /* Compute the size of the shared-memory block */ + size = CalculateShmemSize(&numSemas); elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size); /* diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 467b0fd6fe..872bdc1c8e 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -620,6 +620,8 @@ char *pgstat_temp_directory; char *application_name; +int shmem_size_mb; + int tcp_keepalives_idle; int tcp_keepalives_interval; int tcp_keepalives_count; @@ -2337,6 +2339,17 @@ static struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"shared_memory_size", PGC_INTERNAL, RESOURCES_MEM, + gettext_noop("Shows the amount of shared memory allocated by the server (rounded up to the nearest MB)."), + NULL, + GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_UNIT_MB + }, + &shmem_size_mb, + 0, 0, INT_MAX, + NULL, NULL, NULL + }, + { {"temp_buffers", PGC_USERSET, RESOURCES_MEM, gettext_noop("Sets the maximum number of temporary buffers used by each session."), -- 2.33.0