AW: BUG #17448: In Windows 10, version 1703 and later, huge_pages doesn't work.

From: Wilm Hoyer <W(dot)Hoyer(at)dental-vision(dot)de>
To: Julien Rouhaud <rjuju123(at)gmail(dot)com>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, "pgsql-hackers(at)lists(dot)postgresql(dot)org" <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: AW: BUG #17448: In Windows 10, version 1703 and later, huge_pages doesn't work.
Date: 2022-04-28 09:31:17
Message-ID: 6389b5a88e114bee85593af2853c08cd@dental-vision.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs pgsql-hackers


On Wed, Apr 27, 2022 at 03:04:23PM +0000, Wilm Hoyer wrote:
>>
>> I used the following hack to get the "real" Major and Minor Version of
>> Windows - it's in C# (.Net) and needs to be adjusted (you can compile
>> as x64 and use a long-long as return value ) to return the Service
>> Number too and translated it into C.
>> I share it anyways, as it might help - please be kind, as it really is
>> a little hack.
>>
>> Situation:
>> Main Application can't or is not willing to add a manifest file into
>> its resources.
>>
>> Solution:
>> Start a small executable (which has a manifest file compiled into its
>> resources), let it read the OS Version and code the Version into its
>> return Code.

> Thanks for sharing.

You are welcome.

> Having to compile another tool just for that seems like a very high price to pay, especially since we don't have any C# code in the tree. I'm not even sure that compiling this wouldn't need additional requirements and/or if it would work on our oldest supported Windows versions.

With "translate it into C" I meant "tread it as pseudo code, for a solution in plain C" (e.g. substitude Environment.OSVersion with IsWindowsVersionOrGreater or GetVersion )

On Wed, Apr 27, 2022 at 05:13:12PM +0900, Michael Paquier wrote:
> On Tue, Apr 26, 2022 at 12:54:35PM +0800, Julien Rouhaud wrote:
> > so I'm still on the opinion that we should unconditionally use the
> > FILE_MAP_LARGE_PAGES flag if it's defined and call it a day.
>
> Are we sure that this is not going to cause failures in environments
> where the flag is not supported?

I'm not that familiar with the Microsoft OS or C (that's why I haven't migrated the c# code to C in the first place) to have a clear answer to that question.

If there is any risk and you want to avoid it, I can share a search result when I faced the same issue for our application. I declined this solution in favor of the previously shared one.
It's from NUnit (and needs migration to C as well - but since it just involves the Registry this should be pretty forward).
Just in case the Framework is not known: NUnit is the most popular .Net port of the Unit Testing Framework JUnit. There exits a C port too (CUnit) Maybe in there you can find an OS Version check too.

// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
[...]
namespace NUnit.Framework.Internal
{
[SecuritySafeCritical]
public class OSPlatform
{
[...]
/// <summary>
/// Gets the actual OS Version, not the incorrect value that might be
/// returned for Win 8.1 and Win 10
/// </summary>
/// <remarks>
/// If an application is not manifested as Windows 8.1 or Windows 10,
/// the version returned from Environment.OSVersion will not be 6.3 and 10.0
/// respectively, but will be 6.2 and 6.3. The correct value can be found in
/// the registry.
/// </remarks>
/// <param name="version">The original version</param>
/// <returns>The correct OS version</returns>
private static Version GetWindows81PlusVersion(Version version)
{
try
{
using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"))
{
if (key != null)
{
var buildStr = key.GetValue("CurrentBuildNumber") as string;
int.TryParse(buildStr, out var build);

// These two keys are in Windows 10 only and are DWORDS
var major = key.GetValue("CurrentMajorVersionNumber") as int?;
var minor = key.GetValue("CurrentMinorVersionNumber") as int?;
if (major.HasValue && minor.HasValue)
{
return new Version(major.Value, minor.Value, build);
}

// If we get here, we are not Windows 10, so we are Windows 8
// or 8.1. 8.1 might report itself as 6.2, but will have 6.3
// in the registry. We can't do this earlier because for backwards
// compatibility, Windows 10 also has 6.3 for this key.
var currentVersion = key.GetValue("CurrentVersion") as string;
if(currentVersion == "6.3")
{
return new Version(6, 3, build);
}
}
}
}
catch (Exception)
{
}
return version;
}
[...]
}
}

Finally, my reasoning to use the executable solution in favor of the NUnit one:
I found no guarantee from Microsoft regarding the keys and values in the registry - hence a change with an update or in a newer Windows is not likely, but still possible. That's no problem for a heavily used and supported framework like NUnit - they are likely to adopt within days of a new Windows release. I on the other hand wanted a solution with small to no support. That's why I decided to implement a solution that's as in line as possible with the official Microsoft advice for targeting newer OS Versions.

Best regards
Wilm.

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message PG Bug reporting form 2022-04-28 23:18:17 BUG #17469: postgresql-11.service file not configured to match setup/initdb options specified
Previous Message Masahiko Sawada 2022-04-28 03:40:08 Re: [issue] wal_buffers_full increases depending on the values of wal_buffers and wal-segsize

Browse pgsql-hackers by date

  From Date Subject
Next Message houzj.fnst@fujitsu.com 2022-04-28 10:01:31 RE: Logical replication timeout problem
Previous Message kuroda.hayato@fujitsu.com 2022-04-28 08:34:23 RE: Multi-Master Logical Replication