RFR: 6942632: Hotspot should be able to use more than 64 logical processors on Windows [v3]

David Holmes dholmes at openjdk.org
Wed Feb 28 07:08:46 UTC 2024


On Tue, 27 Feb 2024 22:49:11 GMT, Saint Wesonga <duke at openjdk.org> wrote:

>> Windows processor groups support a maximum of 64 logical processors per processor group. OpenJDK currently uses the GetSystemInfo API to get the number of processors on the system. GetSystemInfo only returns the number of processors in the current processor group, which is at most 64. Therefore, OpenJDK needs to be updated to support the use of all available processors across all Windows processor groups. However, this should only be done when running on Windows 11 or Windows Server 2022 or later Windows operating systems.
>> 
>> Starting with Windows 11 and Windows Server 2022, applications are no longer constrained by default to a single processor group. Instead, processes and their threads have processor affinities that by default span all processors in the system, across multiple groups on machines with more than 64 processors. This is in contrast to previous operating system versions where the processor group affinity APIs needed to be used to assign each thread a specific processor group. See  https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022
>> 
>> The key changes required are:
>> 
>> 1. Detecting Windows 11 or Windows Server 2022 or later.
>> 1. Using the The GetLogicalProcessorInformationEx function to correctly retrieve the total number of processors available on the system. This function was introduced in Windows 7 so its availability needs to be explicitly determined.
>> 1. Updating the calculation of the number of active processors.
>>     1. Processor affinities can be set in a Windows job object and if the JVM is launched in a job object, these affinities restrict the processors that the JVM can use (regardless of how many processors the system has).
>>     1. The JVM can also be launched from the command prompt  by using the start command to set processor affinities instead of using a job object. This command only sets the processor affinity of the primary processor group because it is a 64-bit affinity mask. On systems with over 64 processors, passing an all 1s 64-bit affinity mask to the start command is treated as equivalent to no processor affinity restrictions for the JVM. Any other affinity mask passed to the start command explicitly sets the number of available processors for the JVM and is necessarily at most 63, even if the machine has more than 64 processors.
>>     1. If no affinity restrictions are present, then all cores on the system will be available t...
>
> Saint Wesonga has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Remove implicit casts from int to bool

Seems reasonable in principle but there is a lot of detail here that I'm not familiar with. I will at least take this for a spin in our CI with the flag on and off.

src/hotspot/os/windows/os_windows.cpp line 897:

> 895:   DWORD_PTR lpProcessAffinityMask = 0;
> 896:   DWORD_PTR lpSystemAffinityMask = 0;
> 897:   if (GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) {

I'm struggling to see how we can expose more than 64 processors when our bit-vector is only 64 bits. ??

src/hotspot/os/windows/os_windows.cpp line 901:

> 899:     logical_processors = population_count(lpProcessAffinityMask);
> 900: 
> 901:     if (logical_processors < si.dwNumberOfProcessors) {

The documentation states:
> On a system with more than 64 processors, if the threads of the calling process are in a single [processor group](https://learn.microsoft.com/en-us/windows/desktop/ProcThread/processor-groups), the function sets the variables pointed to by lpProcessAffinityMask and lpSystemAffinityMask to the process affinity mask and the processor mask of active logical processors for that group. If the calling process contains threads in multiple groups, the function returns zero for both affinity masks.

So it seems that we need to do something special to handle zero here.

src/hotspot/os/windows/os_windows.cpp line 906:

> 904:     }
> 905:   } else {
> 906:     warning("GetProcessAffinityMask() failed: GetLastError->%ld.", GetLastError());

Please use `os::lasterror` to output a user-friendly error message.

src/hotspot/os/windows/os_windows.cpp line 4059:

> 4057:   BOOL is_in_job_object = false;
> 4058:   if (IsProcessInJob(GetCurrentProcess(), nullptr, &is_in_job_object) == 0) {
> 4059:     warning("IsProcessInJob() failed: GetLastError->%ld.", GetLastError());

Again please use `os::lasterror`.

src/hotspot/os/windows/os_windows.cpp line 4101:

> 4099:           }
> 4100:         } else {
> 4101:           warning("QueryInformationJobObject() failed: GetLastError->%ld.", GetLastError());

Again use `os::lasterror` please.

src/hotspot/os/windows/os_windows.cpp line 4123:

> 4121:   DWORD returned_length = 0;
> 4122: 
> 4123:   // https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex

There is no need to given URLs for documentation unless there is something very specific about that documentation that is worth linking. We can assume the developer can lookup API reference documents. And URLs get stale.

-------------

PR Review: https://git.openjdk.org/jdk/pull/17576#pullrequestreview-1905440751
PR Review Comment: https://git.openjdk.org/jdk/pull/17576#discussion_r1505441823
PR Review Comment: https://git.openjdk.org/jdk/pull/17576#discussion_r1505442735
PR Review Comment: https://git.openjdk.org/jdk/pull/17576#discussion_r1505443413
PR Review Comment: https://git.openjdk.org/jdk/pull/17576#discussion_r1505446797
PR Review Comment: https://git.openjdk.org/jdk/pull/17576#discussion_r1505448321
PR Review Comment: https://git.openjdk.org/jdk/pull/17576#discussion_r1505449987


More information about the hotspot-runtime-dev mailing list