尝试在高内存,多CPU服务器

时间:2016-02-08 17:08:50

标签: java jvm multiprocessing

我编写了一些基于Java的单线程基因组学软件,一次只运行一个样本,我有数百个样本需要处理。我可以访问具有64个CPU和1TB RAM的计算机,并且系统上没有其他用户。每次调用请求的最大堆大小为8千兆字节。我希望我能够同时调用我的代码的30个实例(假设有两个线程 - 我的主线程和GC线程?)。我只是尝试一次发送20个(使用makefile和-j20参数)。然而,在实践中,只有5次运行。剩下的就是消息:

# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.

可疑这与同时调用有关而非实际资源限制,我在每次调用程序时都在执行循环中实现了几秒钟的随机延迟。这让我最多同时运行10个程序,而不是5个程序,同样的故障信息。

问题:

  1. 为什么试图以这种方式同时调用JVM的几十个实例失败,尽管在明显拥有可用资源的系统上这样做了?

  2. 为什么我的hack实施调度延迟会解决一些问题?

  3. 让所有20个实例同时运行的更好方法是什么?

2 个答案:

答案 0 :(得分:1)

默认收集器是多线程的,并且根据CPU核心数量缩放其线程数。如果你一次运行多个java实例并且每个只有一个线程,你可能想要切换到串行收集器,那么线程堆栈的线程和虚拟内存就会减少。

此外,JVM预先保留了大量虚拟内存,可能比其生命周期中实际需要的内存多。所以你应该启用swap并允许overcommit以避免资源耗尽。

答案 1 :(得分:0)

这不是一个真正的答案,而是一个帮助你研究的指南。

创建一个小的虚拟程序,例如

public final class Test {
    public static void main(String[] args) throws Exception {
        String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
        System.out.println(runtimeName + " Start");
        Thread.sleep(10_000L); // 10 secs
        System.out.println(runtimeName + " End");
    }
}

然后使用-Xms-Xmx同时以固定的内存大小启动它多次。

示例,在Windows上:

for /L %i in (1,1,30) do @start cmd /k java -Xms8G -Xmx8G -cp C:\path\to\class Test

在我的带有32Gb RAM且没有交换文件的Windows 7上,如果我运行了8个4Gb实例,其中3个失败了:

Error occurred during initialization of VM
Could not reserve enough space for object heap

这是预料之中的,因为操作系统和其他程序都在使用内存。我可以看到"提交费用"在Windows资源监视器中最大化。

因此,请尝试此操作并监视操作系统资源。当然,如果不使用Windows,请根据需要调整以上命令。