Hi, > Hi, > > Attached you can find a short (compile tested only ) patch implementing > a 'shared_memory_type' GUC, akin to 'dynamic_shared_memory_type'. Will > only apply to 9.4, not 9.3, but it should be easy to convert for it. > > Greetings, > > Andres Freund
I have rebased Andres's patch against 9.3-STABLE tree. Please take a look at attached patches and let me know if you find anything strange. I am going to test the patch on a huge HP machine: DL980G7/64 cores/2TB mem. With the patch I would be able to report back if using SysV shared mem fixes the 9.3 performance problem. Best regards, -- Tatsuo Ishii SRA OSS, Inc. Japan English: http://www.sraoss.co.jp/index_en.php Japanese:http://www.sraoss.co.jp
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index f746c81..e82054a 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -72,6 +72,7 @@ static void IpcMemoryDetach(int status, Datum shmaddr); static void IpcMemoryDelete(int status, Datum shmId); static PGShmemHeader *PGSharedMemoryAttach(IpcMemoryKey key, IpcMemoryId *shmid); +static void *CreateAnonymousSegment(Size *size); /* @@ -389,49 +390,19 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port) * developer use, this shouldn't be a big problem. */ #ifndef EXEC_BACKEND + if (shared_memory_type == SHMEM_TYPE_MMAP) { - long pagesize = sysconf(_SC_PAGE_SIZE); - - /* - * Ensure request size is a multiple of pagesize. - * - * pagesize will, for practical purposes, always be a power of two. - * But just in case it isn't, we do it this way instead of using - * TYPEALIGN(). - */ - if (pagesize > 0 && size % pagesize != 0) - size += pagesize - (size % pagesize); - - /* - * We assume that no one will attempt to run PostgreSQL 9.3 or later - * on systems that are ancient enough that anonymous shared memory is - * not supported, such as pre-2.4 versions of Linux. If that turns - * out to be false, we might need to add a run-time test here and do - * this only if the running kernel supports it. - */ - AnonymousShmem = mmap(NULL, size, PROT_READ | PROT_WRITE, PG_MMAP_FLAGS, - -1, 0); - if (AnonymousShmem == MAP_FAILED) - { - int saved_errno = errno; - - ereport(FATAL, - (errmsg("could not map anonymous shared memory: %m"), - (saved_errno == ENOMEM) ? - errhint("This error usually means that PostgreSQL's request " - "for a shared memory segment exceeded available memory " - "or swap space. To reduce the request size (currently " - "%lu bytes), reduce PostgreSQL's shared memory usage, " - "perhaps by reducing shared_buffers or " - "max_connections.", - (unsigned long) size) : 0)); - } + AnonymousShmem = CreateAnonymousSegment(&size); AnonymousShmemSize = size; - /* Now we need only allocate a minimal-sized SysV shmem block. */ sysvsize = sizeof(PGShmemHeader); } + else #endif + { + Assert(shared_memory_type == SHMEM_TYPE_SYSV); + sysvsize = size; + } /* Make sure PGSharedMemoryAttach doesn't fail without need */ UsedShmemSegAddr = NULL; @@ -631,3 +602,47 @@ PGSharedMemoryAttach(IpcMemoryKey key, IpcMemoryId *shmid) return hdr; } + +/* + * Creates an anonymous mmap()ed shared memory segment. + * + * Pass the requested size in *size. This function will modify *size to the + * actual size of the allocation, if it ends up allocating a segment that is + * larger than requested. + */ +#ifndef EXEC_BACKEND +static void * +CreateAnonymousSegment(Size *size) +{ + Size allocsize = *size; + void *ptr = MAP_FAILED; + int mmap_errno = 0; + + /* + * use the original size, not the rounded up value, when falling back + * to non-huge pages. + */ + allocsize = *size; + ptr = mmap(NULL, allocsize, PROT_READ | PROT_WRITE, + PG_MMAP_FLAGS, -1, 0); + mmap_errno = errno; + + if (ptr == MAP_FAILED) + { + errno = mmap_errno; + ereport(FATAL, + (errmsg("could not map anonymous shared memory: %m"), + (mmap_errno == ENOMEM) ? + errhint("This error usually means that PostgreSQL's request " + "for a shared memory segment exceeded available memory, " + "swap space or huge pages. To reduce the request size " + "(currently %zu bytes), reduce PostgreSQL's shared " + "memory usage, perhaps by reducing shared_buffers or " + "max_connections.", + *size) : 0)); + } + + *size = allocsize; + return ptr; +} +#endif diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 918ac51..51dccdc 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -39,6 +39,8 @@ #include "storage/sinvaladt.h" #include "storage/spin.h" +/* GUCs */ +int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE; shmem_startup_hook_type shmem_startup_hook = NULL; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 2b6527f..2945a68 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -61,6 +61,7 @@ #include "replication/walreceiver.h" #include "replication/walsender.h" #include "storage/bufmgr.h" +#include "storage/pg_shmem.h" #include "storage/standby.h" #include "storage/fd.h" #include "storage/proc.h" @@ -378,6 +379,19 @@ static const struct config_enum_entry synchronous_commit_options[] = { {NULL, 0, false} }; +static struct config_enum_entry shared_memory_options[] = { +#ifndef WIN32 + { "sysv", SHMEM_TYPE_SYSV, false}, +#endif +#ifndef EXEC_BACKEND + { "mmap", SHMEM_TYPE_MMAP, false}, +#endif +#ifdef WIN32 + { "windows", SHMEM_TYPE_WINDOWS, false}, +#endif + {NULL, 0, false} +}; + /* * Options for enum values stored in other modules */ @@ -3328,6 +3342,16 @@ static struct config_enum ConfigureNamesEnum[] = }, { + {"shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Selects the shared memory implementation used."), + NULL + }, + &shared_memory_type, + DEFAULT_SHARED_MEMORY_TYPE, shared_memory_options, + NULL, NULL, NULL + }, + + { {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS, gettext_noop("Selects the method used for forcing WAL updates to disk."), NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 18196f8..022cf4d 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -124,6 +124,13 @@ #maintenance_work_mem = 16MB # min 1MB #max_stack_depth = 2MB # min 100kB +#shared_memory_type = mmap # the default is the first option + # supported by the operating system: + # mmap + # sysv + # windows +#dynamic_shared_memory_type = posix # the default is the first option + # - Disk - #temp_file_limit = -1 # limits per-session temp file space diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h index 6ece82b..9c3b6d9 100644 --- a/src/include/storage/pg_shmem.h +++ b/src/include/storage/pg_shmem.h @@ -38,6 +38,27 @@ typedef struct PGShmemHeader /* standard header for all Postgres shmem */ #endif } PGShmemHeader; +/* GUC variable */ +extern int huge_pages; +/* Possible values for shared_memory_type */ +typedef enum +{ + SHMEM_TYPE_WINDOWS, + SHMEM_TYPE_SYSV, + SHMEM_TYPE_MMAP +} PGShmemType; + +#if !defined(WIN32) && !defined(EXEC_BACKEND) +#define DEFAULT_SHARED_MEMORY_TYPE SHMEM_TYPE_MMAP +#elif !defined(WIN32) +#define DEFAULT_SHARED_MEMORY_TYPE SHMEM_TYPE_SYSV +#else +#define DEFAULT_SHARED_MEMORY_TYPE SHMEM_TYPE_WINDOWS +#endif + +/* GUC variables */ +extern int shared_memory_type; +extern int huge_pages; #ifdef EXEC_BACKEND #ifndef WIN32
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers