Windows 环境变量 NUMBER_OF_PROCESSORS 在 JVM 内部和外部显示不同的值

Windows environment variable NUMBER_OF_PROCESSORS shows different value within JVM and outside

在我们的 Windows Server 2019 上,我们有 36 个内核和 72 个逻辑处理器,如任务管理器 CPU 性能 window 所示。而且,如果在命令提示符下,如果我 运行 命令。

echo %NUMBER_OF_PROCESSORS%

它告诉我 72。

但是,在 Java 程序中,如果我 运行 下面的代码片段,

public class NoOfCPUs {  
    public static void main(String[] args) {
        String envName = "NUMBER_OF_PROCESSORS";
        String noOfP = System.getenv(envName);
        System.out.format("%s (from env) = %s%n", envName, noOfP);
    }
}

输出如下:

NUMBER_OF_PROCESSORS (from env) = 36

在 Netbeans IDE 中的 Windows 上使用 64 位 Java 8 编译器编译。制作了一个可执行的jar。 运行 罐子,如:

java -jar NoOfCPUs.jar

相同的系统环境变量,NUMBER_OF_PROCESSORS 显示命令提示符与 Java 程序中的不同结果。

为什么?

2009版本后Windows使用的是逻辑处理器组吗?逻辑处理器组在一个组中最多包含 64 个处理器。

这似乎与以下其他问题有关:

  • How to make Java application use all CPU groups
  • Java uses only 1 of 2 CPU with NUMA (Neo4J)

并且此错误报告表示将不支持(不会修复):

https://bugs.openjdk.java.net/browse/JDK-6942632

错误报告说用户应该负责将正确数量的 CPU 配置为 Java,这可以通过以下方式实现:

  1. https://bitsum.com/portfolio/groupextend/
  2. 可能是其他的,因为像 start /affinity 这样的亲和力继承,参见 this answer 但我不能 test/confirm 因为我的笔记本电脑没有那么多内核

我认为你应该考虑 运行 你的应用程序的多个实例(和 Java)而不是仅仅一个以获得最大性能,因为 NUMA 局部性,尽管不同 Java 虚拟机器有 support for NUMA it still might have scalability issues depending on the configured Garbage Collection algorithm (non-concurrent, thus Stop-the-World) see: Amdahls Law

如果该限制特定于 HotSpotVM(源自 Sun/Oracle),您可能需要查看不同的 Java 虚拟机 OpenJ9(源自 IBM)和其他 Azul Zing JVM

如果它是 Windows 特定限制,您可能需要考虑切换到不同的操作系统或 运行 通过您选择的管理程序 Windows 的多个实例。