From e51d8d40dd21697e5a4e2b79be8125bec3707b49 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 1 Sep 2021 18:12:28 +0000 Subject: [PATCH v4 3/3] Introduce huge_pages_required GUC. This runtime-computed GUC shows the number of huge pages required for the server's main shared memory area. It can be viewed with 'postgres -C' so that the huge pages can be allocated prior to startup. --- doc/src/sgml/config.sgml | 16 ++++++++++++++++ doc/src/sgml/runtime.sgml | 27 +++++++++------------------ src/backend/port/sysv_shmem.c | 2 +- src/backend/storage/ipc/ipci.c | 26 ++++++++++++++++++++++++++ src/backend/utils/misc/guc.c | 12 ++++++++++++ src/include/storage/pg_shmem.h | 4 ++++ 6 files changed, 68 insertions(+), 19 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index ef0e2a7746..781147f719 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -10101,6 +10101,22 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + huge_pages_required (integer) + + huge_pages_required configuration parameter + + + + + Reports the number of huge pages that are required for the main + shared memory area based on the specified + . If the huge page size cannot + be determined, this will be -1. + + + + integer_datetimes (boolean) diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 2144c0abad..d955639900 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1444,28 +1444,19 @@ export PG_OOM_ADJUST_VALUE=0 the operating system to provide enough huge pages of the desired size. To estimate the number of huge pages needed, use the postgres command to see the value of - , and use the - /proc and /sys file systems - to find the system's default and supported huge page sizes. This might - look like: + . This might look like: -$ postgres -D $PGDATA -C shared_memory_size -6339 -$ grep ^Hugepagesize /proc/meminfo -Hugepagesize: 2048 kB -$ ls /sys/kernel/mm/hugepages -hugepages-1048576kB hugepages-2048kB +$ postgres -D $PGDATA -C huge_pages_required +3170 - In this example the default is 2MB, but you can also explicitly request - either 2MB or 1GB with . + Note that you can explicitly request either 2MB or 1GB huge pages with + . - Assuming 2MB huge pages, - 6339 / 2 gives - 3169.5, so in this example we need at - least 3170 huge pages. A larger setting would be - appropriate if other programs on the machine also need huge pages. - We can set this with: + While we need at least 3170 huge pages in this + example, a larger setting would be appropriate if other programs on + the machine also need huge pages. We can allocate the huge pages + with: # sysctl -w vm.nr_hugepages=3170 diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index 9de96edf6a..f42f1ac171 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -478,7 +478,7 @@ PGSharedMemoryAttach(IpcMemoryId shmId, * Returns the (real, assumed or config provided) page size into *hugepagesize, * and the hugepage-related mmap flags to use into *mmap_flags. */ -static void +void GetHugePageSize(Size *hugepagesize, int *mmap_flags) { Size default_hugepagesize = 0; diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index f5736703a8..a625dd7701 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -14,6 +14,10 @@ */ #include "postgres.h" +#ifndef WIN32 +#include +#endif + #include "access/clog.h" #include "access/commit_ts.h" #include "access/heapam.h" @@ -326,6 +330,13 @@ InitializeShmemGUCs(void) char buf[64]; Size size_b; Size size_mb; +#if defined(MAP_HUGETLB) || defined(WIN32) + Size hp_size; + Size hp_required; +#endif +#ifdef MAP_HUGETLB + int unused; +#endif /* * Calculate the shared memory size and round up to the nearest @@ -336,4 +347,19 @@ InitializeShmemGUCs(void) sprintf(buf, "%lu MB", size_mb); SetConfigOption("shared_memory_size", buf, PGC_INTERNAL, PGC_S_OVERRIDE); + + /* Calculate the number of huge pages required */ +#if defined(MAP_HUGETLB) + GetHugePageSize(&hp_size, &unused); +#elif defined(WIN32) + hp_size = GetLargePageMinimum(); +#endif + +#if defined(MAP_HUGETLB) || defined(WIN32) + if (hp_size == 0) + return; + hp_required = (size_b / hp_size) + 1; + sprintf(buf, "%lu", hp_required); + SetConfigOption("huge_pages_required", buf, PGC_INTERNAL, PGC_S_OVERRIDE); +#endif } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a11387c5ce..3e9a01746e 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -621,6 +621,7 @@ char *pgstat_temp_directory; char *application_name; int shmem_size_mb; +int huge_pages_required; int tcp_keepalives_idle; int tcp_keepalives_interval; @@ -2225,6 +2226,17 @@ static struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"huge_pages_required", PGC_INTERNAL, RESOURCES_MEM, + gettext_noop("Shows the number of huge pages needed for the main shared memory area."), + gettext_noop("-1 indicates that the huge page size could not be determined."), + GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + }, + &huge_pages_required, + -1, -1, INT_MAX, + NULL, NULL, NULL + }, + { /* This is PGC_SUSET to prevent hiding from log_lock_waits. */ {"deadlock_timeout", PGC_SUSET, LOCK_MANAGEMENT, diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h index 059df1b72c..c44403ed6a 100644 --- a/src/include/storage/pg_shmem.h +++ b/src/include/storage/pg_shmem.h @@ -88,4 +88,8 @@ extern PGShmemHeader *PGSharedMemoryCreate(Size size, extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2); extern void PGSharedMemoryDetach(void); +#ifdef MAP_HUGETLB +extern void GetHugePageSize(Size *hugepagesize, int *mmap_flags); +#endif + #endif /* PG_SHMEM_H */ -- 2.16.6