在64位Java中估算最大安全的JVM堆大小

8
在分析一款存在问题的64位Java应用程序时,我注意到分析器本身(YourKit)使用了非常大量的内存。在YourKit启动脚本中,我有以下内容:
JAVA_HEAP_LIMIT="-Xmx3072m -XX:PermSize=256m -XX:MaxPermSize=768m"

粗略地估计,考虑到一些开销,我的猜测是YourKit将使用最多略高于4GB的内存。然而,实际在PS中看到的是:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
dmoles   31379  4.4 68.2 14440032 8321396 ?    Sl   11:47  10:42 java -Xmx3072m -XX:PermSize=256m -XX:MaxPermSize=768m -XX:+HeapDumpOnOutOfMemoryError -Dyjp.probe.table.length.limit=20000 -Xbootclasspath/a:/home/dmoles/Applications/yjp-9.5.6/bin/../lib/tools.jar -jar /home/dmoles/Applications/yjp-9.5.6/bin/../lib/yjp.jar

这是一个虚拟大小接近14 GB,常驻大小接近8 GB的程序,几乎是Java堆的3倍。

现在,我的开发机器上有足够的内存来运行它,但回到我正在尝试诊断的原始内存问题:如何知道我有多少Java堆可以使用?

显然,如果客户有16 GB物理RAM,让他们将-Xmx设置为16 GB并不是一个好主意。

那么什么是合理的数字?12 GB?8 GB?

我如何估算它?

1个回答

10
显然,如果客户有16 GB的物理内存,则让他们将-Xmx设置为16 GB并不是一个好主意。 如果客户机上没有运行其他重要内容,则将堆大小设置为16G并不一定是一个坏主意。这取决于应用程序正在做什么。
那么什么是合理的数字?12 GB?8 GB? 理想数字应该是“JVM最大堆+ JVM非堆开销+操作系统+其他活动应用程序的工作集+缓冲区缓存工作集”的总和等于物理内存的数量。但问题在于,除了最大堆大小之外,没有哪个组件(除了最大堆大小)可以在客户机上详细测量……而应用程序正在解决实际问题时进行测量。
那我如何估计它? 底线是你不能。你能做的最好的事情就是猜测…保守一些。
另一种方法是估计应用程序实际上需要解决问题所需的堆大小。然后添加额外的50%或100%以使垃圾回收有足够的空间有效地工作。(然后调整...)

对于估计应用程序需要多少堆空间并从那里开始的想法表示赞同。 “如何估计”这个问题让我想起了Eric Lippert关于“线程幸福病”的帖子。 - Adam Mihalcin
@AdamMihalcin 这是个好建议,但问题有两面。正面(估计应用程序需要多少)是,“我们预计会有多少用户;我们应该购买多少服务器?”反面则是,“我们拥有多少服务器;在内存耗尽之前,我们能处理多少用户?” - David Moles
所以Stephen,当你说“增加额外的50或100%以使GC有足够的空间高效工作”时,你是指将其添加到JVM堆大小中,还是指拥有那么多的空闲RAM?我猜这里我需要理解“JVM非堆开销”。 - David Moles
@DavidMoles - 1)估算/计算应用程序运行所需的内存量。2)将该数字乘以1.5或2.0,并将其用作堆大小。3)进行调整。4)公开向所有人承认这只是猜测...因为这就是实际情况。 - Stephen C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接