Re: Perfomance degradation 9.3 (vs 9.2) for FreeBSD

Palle Girgensohn <girgen@freebsd.org>

From: Palle Girgensohn <girgen@FreeBSD.org>
To: Tatsuo Ishii <ishii@postgresql.org>
Cc: andres@2ndquadrant.com, PostgreSQL Hackers <pgsql-hackers@postgresql.org>, robertmhaas@gmail.com, ftigeot@wolfpond.org
Date: 2014-10-20T13:09:00Z
Lists: pgsql-hackers

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Add shared_memory_type GUC.

Hello,

How did this testing turn out?

Palle

3 jul 2014 kl. 12:15 skrev Tatsuo Ishii <ishii@postgresql.org>:

> 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