From 4ef008bd7fb4ad7a6c7c0fbd070ef571429c046c Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 16 Sep 2021 16:35:55 +0000 Subject: [PATCH v11 1/1] Introduce shared_memory_size_in_huge_pages GUC. This runtime-computed GUC shows the number of huge pages required for the server's main shared memory area. --- doc/src/sgml/config.sgml | 20 ++++++++++++++++++++ doc/src/sgml/ref/postgres-ref.sgml | 3 ++- doc/src/sgml/runtime.sgml | 30 ++++++++++-------------------- src/backend/port/sysv_shmem.c | 16 +++++++++++----- src/backend/port/win32_shmem.c | 14 ++++++++++++++ src/backend/storage/ipc/ipci.c | 14 ++++++++++++++ src/backend/utils/misc/guc.c | 12 ++++++++++++ src/include/storage/pg_shmem.h | 1 + 8 files changed, 84 insertions(+), 26 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index ef0e2a7746..6e8839cd1b 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -10289,6 +10289,26 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + shared_memory_size_in_huge_pages (integer) + + shared_memory_size_in_huge_pages configuration parameter + + + + + Reports the number of huge pages that are needed for the main shared + memory area based on the specified . + If huge pages are not supported, this will be -1. + + + This setting is supported only on Linux. It is always set to + -1 on other platforms. For more details about using + huge pages on Linux, see . + + + + ssl_library (string) diff --git a/doc/src/sgml/ref/postgres-ref.sgml b/doc/src/sgml/ref/postgres-ref.sgml index f72c3b04e4..55a3f6c69d 100644 --- a/doc/src/sgml/ref/postgres-ref.sgml +++ b/doc/src/sgml/ref/postgres-ref.sgml @@ -143,7 +143,8 @@ PostgreSQL documentation This can be used on a running server for most parameters. However, the server must be shut down for some runtime-computed parameters - (e.g., and + (e.g., , + , and ). diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index f1cbc1d9e9..9310859506 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1442,31 +1442,21 @@ export PG_OOM_ADJUST_VALUE=0 with CONFIG_HUGETLBFS=y and CONFIG_HUGETLB_PAGE=y. You will also have to configure the operating system to provide enough huge pages of the desired size. - To estimate the number of huge pages needed, start - PostgreSQL without huge pages enabled and check - the postmaster's anonymous shared memory segment size, as well as the - system's default and supported huge page sizes, using the - /proc and /sys file systems. + To determine the number of huge pages needed, use the + postgres command to see the value of + . This might look like: -$ head -1 $PGDATA/postmaster.pid -4170 -$ pmap 4170 | awk '/rw-s/ && /zero/ {print $2}' -6490428K -$ grep ^Hugepagesize /proc/meminfo -Hugepagesize: 2048 kB -$ ls /sys/kernel/mm/hugepages -hugepages-1048576kB hugepages-2048kB +$ postgres -D $PGDATA -C shared_memory_size_in_huge_pages +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, - 6490428 / 2048 gives approximately - 3169.154, 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. + 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 set this 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..125e2d47ec 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -456,8 +456,6 @@ PGSharedMemoryAttach(IpcMemoryId shmId, return shmStat.shm_nattch == 0 ? SHMSTATE_UNATTACHED : SHMSTATE_ATTACHED; } -#ifdef MAP_HUGETLB - /* * Identify the huge page size to use, and compute the related mmap flags. * @@ -476,11 +474,19 @@ PGSharedMemoryAttach(IpcMemoryId shmId, * such as increasing shared_buffers to absorb the extra space. * * Returns the (real, assumed or config provided) page size into *hugepagesize, - * and the hugepage-related mmap flags to use into *mmap_flags. + * and the hugepage-related mmap flags to use into *mmap_flags. If huge pages + * is not supported, *hugepagesize and *mmap_flags will be set to 0. */ -static void +void GetHugePageSize(Size *hugepagesize, int *mmap_flags) { +#ifndef MAP_HUGETLB + + *hugepagesize = 0; + *mmap_flags = 0; + +#else + Size default_hugepagesize = 0; /* @@ -553,9 +559,9 @@ GetHugePageSize(Size *hugepagesize, int *mmap_flags) *mmap_flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT; } #endif -} #endif /* MAP_HUGETLB */ +} /* * Creates an anonymous mmap()ed shared memory segment. diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c index d7a71992d8..90de2ab4e1 100644 --- a/src/backend/port/win32_shmem.c +++ b/src/backend/port/win32_shmem.c @@ -605,3 +605,17 @@ pgwin32_ReserveSharedMemoryRegion(HANDLE hChild) return true; } + +/* + * This function is provided for consistency with sysv_shmem.c and does not + * provide any useful information for Windows. To obtain the large page size, + * use GetLargePageMinimum() instead. + * + * This always sets *hugepagesize and *mmap_flags to 0. + */ +void +GetHugePageSize(Size *hugepagesize, int *mmap_flags) +{ + *hugepagesize = 0; + *mmap_flags = 0; +} diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 13f3926ff6..805d807906 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -326,6 +326,9 @@ InitializeShmemGUCs(void) char buf[64]; Size size_b; Size size_mb; + Size hp_size; + Size hp_required; + int unused; /* * Calculate the shared memory size and round up to the nearest megabyte. @@ -334,4 +337,15 @@ InitializeShmemGUCs(void) size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024); sprintf(buf, "%zu", size_mb); SetConfigOption("shared_memory_size", buf, PGC_INTERNAL, PGC_S_OVERRIDE); + + /* + * Calculate the number of huge pages required. + */ + GetHugePageSize(&hp_size, &unused); + if (hp_size != 0) + { + hp_required = add_size(size_b / hp_size, 1); + sprintf(buf, "%zu", hp_required); + SetConfigOption("shared_memory_size_in_huge_pages", buf, PGC_INTERNAL, PGC_S_OVERRIDE); + } } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a6e4fcc24e..d2ce4a8450 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -665,6 +665,7 @@ static int max_identifier_length; static int block_size; static int segment_size; static int shared_memory_size_mb; +static int shared_memory_size_in_huge_pages; static int wal_block_size; static bool data_checksums; static bool integer_datetimes; @@ -2349,6 +2350,17 @@ static struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"shared_memory_size_in_huge_pages", PGC_INTERNAL, PRESET_OPTIONS, + gettext_noop("Shows the number of huge pages needed for the main shared memory area."), + gettext_noop("-1 indicates that the value could not be determined."), + GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED + }, + &shared_memory_size_in_huge_pages, + -1, -1, INT_MAX, + NULL, NULL, NULL + }, + { {"temp_buffers", PGC_USERSET, RESOURCES_MEM, gettext_noop("Sets the maximum number of temporary buffers used by each session."), diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h index 059df1b72c..518eb86065 100644 --- a/src/include/storage/pg_shmem.h +++ b/src/include/storage/pg_shmem.h @@ -87,5 +87,6 @@ extern PGShmemHeader *PGSharedMemoryCreate(Size size, PGShmemHeader **shim); extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2); extern void PGSharedMemoryDetach(void); +extern void GetHugePageSize(Size *hugepagesize, int *mmap_flags); #endif /* PG_SHMEM_H */ -- 2.16.6