Re: Supporting huge pages on Windows

From: "Tsunakawa, Takayuki" <tsunakawa(dot)takay(at)jp(dot)fujitsu(dot)com>
To: 'Amit Kapila' <amit(dot)kapila16(at)gmail(dot)com>
Cc: Magnus Hagander <magnus(at)hagander(dot)net>, Robert Haas <robertmhaas(at)gmail(dot)com>, "pgsql-hackers(at)postgresql(dot)org" <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Supporting huge pages on Windows
Date: 2017-01-10 03:19:37
Message-ID: 0A3221C70F24FB45833433255569204D1F673312@G01JPEXMBYT05
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hello, Amit, Magnus,

I'm sorry for my late reply. Yesterday was a national holiday in Japan.

From: pgsql-hackers-owner(at)postgresql(dot)org
> [mailto:pgsql-hackers-owner(at)postgresql(dot)org] On Behalf Of Amit Kapila
> PGSharedMemoryReAttach is called after the startup of new process whereas
> pgwin32_ReserveSharedMemoryRegion is called before the new process could
> actually start. Basically, pgwin32_ReserveSharedMemoryRegion is used to
> reserve shared memory for each backend, so calling VirtualAlloc there should
> follow spec for huge pages. If you have some reason for not using, then
> it is not clear from your reply, can you try to explain in detail.

OK. The processing takes place in the following order:

1. postmaster calls CreateProcess() to start a child postgres in a suspended state.
2. postmaster calls VirtualAlloc(MEM_RESERVE) in pgwin32_ReserveSharedMemoryRegion() to reserve the virtual address space in the child to secure space for the shared memory. This call just affects the virtual address space and does not allocate physical memory. So the large page is still irrelevant.
3. postmaster resumes execution of the child postgres.
4. The child postgres calls VirtualFree(MEM_RESERVE) in PGSharedMemoryReAttach() to release the reserved virtual address space. Here, the effect of VirtualAlloc() is invalidated anyway.
5. The child process calls MapViewOfFile() in PGSharedMemoryReAttach() to map the shared memory at the same address. Hereafter, the large page option specified in CreateFileMapping() call is relevant.

> + if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luid)) {
> + CloseHandle(hToken); ereport(elevel, (errmsg("could not enable Lock
> + pages in memory user right: error
> code %lu", GetLastError()),
> + errdetail("Failed system call was LookupPrivilegeValue."))); return
> + FALSE; }
>
> The order of closing handle and ereport is different here than other places
> in the same function. If there is no specific reason for doing so, then
> keep the order consistent.

You are right, I modified the patch to call CloseHandle() after ereport() so that ereport() CloseHandle() wouldn't change the error code for ereport(). That's the order used in postmaster.c.

> I have tried to test v4 version of the patch and it is always failing in
> below error after call to AdjustTokenPrivileges:
>
> + if (GetLastError() != ERROR_SUCCESS)
> + {
> + 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.")));
>
> I have ensured that user used to run PostgreSQL has "Lock pages in memory"
> privilege/rights. I have followed msdn tips [1] to do that (restarted the
> m/c after assigning privilege). I am using Win7. Can you share the steps
> you have followed to test and your windows m/c details?
>
> [1] -
> https://msdn.microsoft.com/en-us/library/windows/desktop/ff961911(v=vs
> .85).aspx

I succeeded by following the same procedure using secpol.msc on Win10, running 64-bit PostgreSQL. I started PostgreSQL as a Windows service because it's the normal way, with the service account being a regular Windows user account(i.e. not LocalSystem).

But... I failed to start PostgreSQL by running "pg_ctl start" from a command prompt, receiving the same error message as you. On the other hand, I could start PostgreSQL on a command prompt with administrative privileges (right-click on "Command prompt" from the Start menu and select "Run as an administrator" in the menu. It seems that Windows removes many privileges, including "Lock Pages in Memory", when starting the normal command prompt. As its evidence, you can use the attached priv.c to see what privileges are assigned and and enabled/disabled. Build it like "cl priv.c" and just run priv.exe on each command prompt. Those runs show different privileges.

Should I need to do something, e.g. explain in the document that the user should use the command prompt with administrative privileges when he uses huge_pages?

Regards
Takayuki Tsunakawa

Attachment Content-Type Size
win_large_pages_v6.patch application/octet-stream 6.9 KB
priv.c text/plain 1.6 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Amit Kapila 2017-01-10 03:46:48 Re: _hash_addovflpage has a bug
Previous Message Erik Rijkers 2017-01-10 03:08:18 Re: WIP: Covering + unique indexes.