我编写了一些基于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个程序,同样的故障信息。
问题:
为什么试图以这种方式同时调用JVM的几十个实例失败,尽管在明显拥有可用资源的系统上这样做了?
为什么我的hack实施调度延迟会解决一些问题?
让所有20个实例同时运行的更好方法是什么?
答案 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,请根据需要调整以上命令。