diff -Nacr a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
*** a/doc/src/sgml/config.sgml 2016-09-20 05:17:08.000000000 +0900
--- b/doc/src/sgml/config.sgml 2016-09-26 11:38:01.000000000 +0900
***************
*** 1336,1352 ****
! At present, this feature is supported only on Linux. The setting is
! ignored on other systems when set to try.
The use of huge pages results in smaller page tables and less CPU time
! spent on memory management, increasing performance. For more details,
see .
With huge_pages set to try,
the server will try to use huge pages, but fall back to using
normal allocation if that fails. With on, failure
--- 1336,1358 ----
! At present, this feature is supported only on Linux and Windows. The
! setting is ignored on other systems when set to try.
The use of huge pages results in smaller page tables and less CPU time
! spent on memory management, increasing performance. For more details on Linux,
see .
+ This feature uses the large-page support on Windows. To use the large-page
+ support, you need to assign Lock page in memory user right to the Windows
+ user account which runs PostgreSQL.
+
+
+
With huge_pages set to try,
the server will try to use huge pages, but fall back to using
normal allocation if that fails. With on, failure
diff -Nacr a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
*** a/src/backend/port/win32_shmem.c 2016-09-20 05:17:08.000000000 +0900
--- b/src/backend/port/win32_shmem.c 2016-09-26 11:07:59.000000000 +0900
***************
*** 21,26 ****
--- 21,27 ----
void *UsedShmemSegAddr = NULL;
static Size UsedShmemSegSize = 0;
+ static bool EnableLockPagesPrivilege(int elevel);
static void pgwin32_SharedMemoryDelete(int status, Datum shmId);
/*
***************
*** 103,108 ****
--- 104,164 ----
return true;
}
+ /*
+ * EnableLockPagesPrivilege
+ *
+ * Try to acquire SeLockMemoryPrivilege so we can use large pages.
+ */
+ static bool
+ EnableLockPagesPrivilege(int elevel)
+ {
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tp;
+ LUID luid;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+ {
+ ereport(elevel,
+ (errmsg("could not enable Lock pages in memory user right"),
+ errdetail("Failed system call was %s, error code %lu", "OpenProcessToken", GetLastError())));
+ return FALSE;
+ }
+
+ if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luid))
+ {
+ CloseHandle(hToken);
+ ereport(elevel,
+ (errmsg("could not enable Lock pages in memory user right"),
+ errdetail("Failed system call was %s, error code %lu", "LookupPrivilegeValue", GetLastError())));
+ return FALSE;
+ }
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
+ {
+ ereport(elevel,
+ (errmsg("could not enable Lock pages in memory user right"),
+ errdetail("Failed system call was %s, error code %lu", "AdjustTokenPrivileges", GetLastError())));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+
+ if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+ {
+ ereport(elevel,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("could not enable Lock pages in memory user right"),
+ errhint("Assign Lock pages in memory user right to the Windows user account which runs PostgreSQL.")));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+
+ CloseHandle(hToken);
+
+ return TRUE;
+ }
/*
* PGSharedMemoryCreate
***************
*** 127,137 ****
int i;
DWORD size_high;
DWORD size_low;
!
! if (huge_pages == HUGE_PAGES_ON)
! ereport(ERROR,
! (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! errmsg("huge pages not supported on this platform")));
/* Room for a header? */
Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
--- 183,190 ----
int i;
DWORD size_high;
DWORD size_low;
! SIZE_T largePageSize = 0;
! DWORD flProtect;
/* Room for a header? */
Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
***************
*** 140,145 ****
--- 193,235 ----
UsedShmemSegAddr = NULL;
+ if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY)
+ {
+ /* Does the processor support large pages? */
+ largePageSize = GetLargePageMinimum();
+ if (largePageSize == 0)
+ {
+ ereport(huge_pages == HUGE_PAGES_ON ? FATAL : DEBUG1,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("the processor does not support large pages")));
+ ereport(DEBUG1,
+ (errmsg("disabling huge pages")));
+ huge_pages = HUGE_PAGES_OFF;
+ }
+ }
+
+ if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY)
+ {
+ /* Enable Lock pages in memory user right. */
+ if (!EnableLockPagesPrivilege(huge_pages == HUGE_PAGES_ON ? FATAL : DEBUG1))
+ {
+ ereport(DEBUG1,
+ (errmsg("disabling huge pages")));
+ huge_pages = HUGE_PAGES_OFF;
+ }
+ }
+
+ if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY)
+ {
+ flProtect = PAGE_READWRITE | SEC_COMMIT | SEC_LARGE_PAGES;
+
+ /* Round size up as appropriate. */
+ if (size % largePageSize != 0)
+ size += largePageSize - (size % largePageSize);
+ }
+ else
+ flProtect = PAGE_READWRITE;
+
#ifdef _WIN64
size_high = size >> 32;
#else
***************
*** 163,169 ****
hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */
NULL, /* Default security attrs */
! PAGE_READWRITE, /* Memory is Read/Write */
size_high, /* Size Upper 32 Bits */
size_low, /* Size Lower 32 bits */
szShareMem);
--- 253,259 ----
hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */
NULL, /* Default security attrs */
! flProtect,
size_high, /* Size Upper 32 Bits */
size_low, /* Size Lower 32 bits */
szShareMem);
diff -Nacr a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
*** a/src/backend/utils/misc/guc.c 2016-09-20 05:17:08.000000000 +0900
--- b/src/backend/utils/misc/guc.c 2016-09-26 11:10:56.000000000 +0900
***************
*** 3792,3798 ****
{
{"huge_pages", PGC_POSTMASTER, RESOURCES_MEM,
! gettext_noop("Use of huge pages on Linux."),
NULL
},
&huge_pages,
--- 3792,3798 ----
{
{"huge_pages", PGC_POSTMASTER, RESOURCES_MEM,
! gettext_noop("Use of huge pages on Linux/Windows."),
NULL
},
&huge_pages,