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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers