我正在计算群集上运行多个作业,当它们超过请求的资源使用时会被杀死 - 其中一个用途是虚拟内存大小。
在我的java启动命令中,我使用-Xmx8000m
来表示初始堆栈大小为8GB,我还没有看到我的程序的实际内存使用量超过4GB,但是为了安全起见。
但是,当我使用top命令时,我看到我的java进程的虚拟内存大小为12GB - 正好在所请求的虚拟内存空间的限制。由于作业已经提交,我无法增加我所请求的VM大小,而且我要求他们花费的时间越长。
Java是否一致地请求比指定的VM堆空间更多?这是一个恒定的数量,或恒定的%或随机?堆空间是否可以增长到a)请求的VM大小(8GB)或b)分配的VM大小(12GB)。
编辑: 在Linux上使用jre-1.7.0-openjdk
答案 0 :(得分:7)
本文对该问题进行了很好的分析:Why does my Java process consume more memory than Xmx其作者提供了这个近似公式:
Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]
但除了应用程序消耗的内存之外,还有JVM本身 还需要一些肘部空间。 - 垃圾收集。 - JIT优化。 - 堆外分配。 - JNI代码。 - Metaspace。
但要小心,因为它可能取决于平台和JVM供应商/版本。
答案 1 :(得分:4)
这可能是由于glibc 2.10+中malloc行为的变化,malloc现在创建了每线程内存池(竞技场)。 64位的竞技场大小为64MB。在64位上使用8个竞技场之后,malloc将竞技场的数量设置为number_of_cpus * 8.因此,如果您使用的是具有多个处理器核心的计算机,则即使实际内存,虚拟大小也会非常快速地设置使用(居民大小)要小得多。
由于您看到顶级显示12GB虚拟大小,您可能正在使用具有24个内核或硬件线程的64位计算机,提供24 * 8 * 64MB = 12GB。分配的虚拟内存量因内核数量而异,并且数量将根据您的作业发送到的计算机上的内核数量而变化,因此此检查没有意义。
如果您使用hadoop或yarn并获取,请将yarn-site.xml中的yarn.nodemanager.vmem-check-enabled
设置为false
。
参考文献:
请参阅本页第6页:
http://blog.cloudera.com/blog/2014/04/apache-hadoop-yarn-avoiding-6-time-consuming-gotchas/
链接到此页面上的更深入讨论:
请注意,此stackoverflow页面已经部分回答:
答案 2 :(得分:0)
您真的很想调查此问题并且您在Linux上然后检查您的jvm进程的PID并查看文件/proc/<PID>/smaps
。在那里,您将找到整个操作系统进程内存映射 - 如内核所示。您将看到mach堆(OS堆)进程如何使用,哪些内存区域从文件(库)映射,等等。
PS:你也可以在互联网上提交各种工具来分析smaps文件。