Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb0fc0df

Browse files
committed
Dramatically reduce System V shared memory consumption.
Except when compiling with EXEC_BACKEND, we'll now allocate only a tinyamount of System V shared memory (as an interlock to protect the datadirectory) and allocate the rest as anonymous shared memory via mmap.This will hopefully spare most users the hassle of adjusting operatingsystem parameters before being able to start PostgreSQL with areasonable value for shared_buffers.There are a bunch of documentation updates needed here, and we mightneed to adjust some of the HINT messages related to shared memory aswell. But it's not 100% clear how portable this is, so before wewrite the documentation, let's give it a spin on the buildfarm andsee what turns red.
1 parentc5b3451 commitb0fc0df

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

‎src/backend/port/sysv_shmem.c

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include<signal.h>
2020
#include<unistd.h>
2121
#include<sys/file.h>
22+
#include<sys/mman.h>
2223
#include<sys/stat.h>
2324
#ifdefHAVE_SYS_IPC_H
2425
#include<sys/ipc.h>
@@ -43,9 +44,22 @@ typedef int IpcMemoryId;/* shared memory ID returned by shmget(2) */
4344
#definePG_SHMAT_FLAGS0
4445
#endif
4546

47+
/* Linux prefers MAP_ANONYMOUS, but the flag is called MAP_ANON on other systems. */
48+
#ifndefMAP_ANONYMOUS
49+
#defineMAP_ANONYMOUSMAP_ANON
50+
#endif
51+
52+
/* BSD-derived systems have MAP_HASSEMAPHORE, but it's not present (or needed) on Linux. */
53+
#ifndefMAP_HASSEMAPHORE
54+
#defineMAP_HASSEMAPHORE0
55+
#endif
56+
57+
#definePG_MMAP_FLAGS(MAP_SHARED|MAP_ANONYMOUS|MAP_HASSEMAPHORE)
4658

4759
unsigned longUsedShmemSegID=0;
4860
void*UsedShmemSegAddr=NULL;
61+
staticSizeAnonymousShmemSize;
62+
staticPGShmemHeader*AnonymousShmem;
4963

5064
staticvoid*InternalIpcMemoryCreate(IpcMemoryKeymemKey,Sizesize);
5165
staticvoidIpcMemoryDetach(intstatus,Datumshmaddr);
@@ -218,8 +232,13 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
218232
staticvoid
219233
IpcMemoryDetach(intstatus,Datumshmaddr)
220234
{
235+
/* Detach System V shared memory block. */
221236
if (shmdt(DatumGetPointer(shmaddr))<0)
222237
elog(LOG,"shmdt(%p) failed: %m",DatumGetPointer(shmaddr));
238+
/* Release anonymous shared memory block, if any. */
239+
if (AnonymousShmem!=NULL
240+
&&munmap(AnonymousShmem,AnonymousShmemSize)<0)
241+
elog(LOG,"munmap(%p) failed: %m",AnonymousShmem);
223242
}
224243

225244
/****************************************************************************/
@@ -357,10 +376,59 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
357376
PGShmemHeader*hdr;
358377
IpcMemoryIdshmid;
359378
structstatstatbuf;
379+
Sizeallocsize=size;
360380

361381
/* Room for a header? */
362382
Assert(size>MAXALIGN(sizeof(PGShmemHeader)));
363383

384+
/*
385+
* As of PostgreSQL 9.3, we normally allocate only a very small amount of
386+
* System V shared memory, and only for the purposes of providing an
387+
* interlock to protect the data directory. The real shared memory block
388+
* is allocated using mmap(). This works around the problem that many
389+
* systems have very low limits on the amount of System V shared memory
390+
* that can be allocated. Even a limit of a few megabytes will be enough
391+
* to run many copies of PostgreSQL without needing to adjust system
392+
* settings.
393+
*
394+
* However, we disable this logic in the EXEC_BACKEND case, and fall back
395+
* to the old method of allocating the entire segment using System V shared
396+
* memory, because there's no way to attach an mmap'd segment to a process
397+
* after exec(). Since EXEC_BACKEND is intended only for developer use,
398+
* this shouldn't be a big problem.
399+
*/
400+
#ifndefEXEC_BACKEND
401+
{
402+
longpagesize=sysconf(_SC_PAGE_SIZE);
403+
404+
/*
405+
* pagesize will, for practical purposes, always be a power of two.
406+
* But just in case it isn't, we do it this way instead of using
407+
* TYPEALIGN().
408+
*/
409+
AnonymousShmemSize=size;
410+
if (size %pagesize!=0)
411+
AnonymousShmemSize+=pagesize- (size %pagesize);
412+
413+
/*
414+
* We assume that no one will attempt to run PostgreSQL 9.3 or later
415+
* on systems that are ancient enough that anonymous shared memory is
416+
* not supported, such as pre-2.4 versions of Linux. If that turns out
417+
* to be false, we might need to add a run-time test here and do this
418+
* only if the running kernel supports it.
419+
*/
420+
AnonymousShmem=mmap(NULL,size,PROT_READ|PROT_WRITE,PG_MMAP_FLAGS,
421+
-1,0);
422+
if (AnonymousShmem==NULL)
423+
ereport(FATAL,
424+
(errmsg("could not map %lu bytes of anonymous shared memory: %m",
425+
(unsigned long)AnonymousShmemSize)));
426+
427+
/* Now we can allocate a minimal SHM block. */
428+
allocsize=sizeof(PGShmemHeader);
429+
}
430+
#endif
431+
364432
/* Make sure PGSharedMemoryAttach doesn't fail without need */
365433
UsedShmemSegAddr=NULL;
366434

@@ -370,7 +438,7 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
370438
for (NextShmemSegID++;;NextShmemSegID++)
371439
{
372440
/* Try to create new segment */
373-
memAddress=InternalIpcMemoryCreate(NextShmemSegID,size);
441+
memAddress=InternalIpcMemoryCreate(NextShmemSegID,allocsize);
374442
if (memAddress)
375443
break;/* successful create and attach */
376444

@@ -409,7 +477,7 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
409477
/*
410478
* Now try again to create the segment.
411479
*/
412-
memAddress=InternalIpcMemoryCreate(NextShmemSegID,size);
480+
memAddress=InternalIpcMemoryCreate(NextShmemSegID,allocsize);
413481
if (memAddress)
414482
break;/* successful create and attach */
415483

@@ -448,7 +516,17 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
448516
UsedShmemSegAddr=memAddress;
449517
UsedShmemSegID= (unsigned long)NextShmemSegID;
450518

451-
returnhdr;
519+
/*
520+
* If AnonymousShmem is NULL here, then we're not using anonymous shared
521+
* memory, and should return a pointer to the System V shared memory block.
522+
* Otherwise, the System V shared memory block is only a shim, and we must
523+
* return a pointer to the real block.
524+
*/
525+
if (AnonymousShmem==NULL)
526+
returnhdr;
527+
memcpy(AnonymousShmem,hdr,sizeof(PGShmemHeader));
528+
returnAnonymousShmem;
529+
452530
}
453531

454532
#ifdefEXEC_BACKEND
@@ -516,6 +594,11 @@ PGSharedMemoryDetach(void)
516594
elog(LOG,"shmdt(%p) failed: %m",UsedShmemSegAddr);
517595
UsedShmemSegAddr=NULL;
518596
}
597+
598+
/* Release anonymous shared memory block, if any. */
599+
if (AnonymousShmem!=NULL
600+
&&munmap(AnonymousShmem,AnonymousShmemSize)<0)
601+
elog(LOG,"munmap(%p) failed: %m",AnonymousShmem);
519602
}
520603

521604

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp