代码之家  ›  专栏  ›  技术社区  ›  LB40

如何选择JVM堆大小?

  •  24
  • LB40  · 技术社区  · 15 年前

    我通常对JVM堆大小做的是将最大值设置得非常高,以避免出现臭名昭著的OutofMemoryException。

    然而,这种策略(或缺乏策略)似乎并不真正明智。:-)

    我的问题是如何选择最小值和最大值,以及两者之间的差异(最大值和最小值应该是小的还是大的?). 例如,从 here :

    如果初始堆太小,则 Java应用程序启动速度变慢 因为JVM被迫执行 经常收集垃圾直到 堆已经长大了 尺寸合理。用于最佳启动 性能您应该设置初始 堆大小与最大值相同 堆大小。

    谢谢。

    6 回复  |  直到 12 年前
        1
  •  19
  •   Bob Cross n8wrl    15 年前

    我的问题是如何选择最小值 和最大值,以及差异 两者之间(最大值最小值应为 小还是大?)

    简短回答: 别猜了,介绍一下你的应用程序。

    jconsole can give you useful high-level data 例如,对主要常驻集的感觉与我们通常分配和垃圾收集的临时数据的对比。如果你看到显示器上的记忆标签,你会看到的通常是锯齿状的。锯齿的下角大约是我通常设置堆最小值的地方,而我将使用锯齿的峰值或斜率来测试堆最大值。如果你的牙齿非常陡峭,你可以考虑一个大的堆来延迟垃圾收集。但是,如果不是这样,您可以尝试使用较小的堆最大值,看看这是否会为您的计算机上的其他进程留下更多的资源(例如)。

    你也应该考虑 server VM 因为这将导致不同的垃圾收集行为。

    尽管如此,您还应该使用更详细的工具,例如 jvisualvm to profile the memory usage of your process . 有可能您有一个内存泄漏或贪婪的分配器,您可以对其进行优化或消除。这将完全改变您的堆需求。

        2
  •  5
  •   Jé Queue    15 年前

    您应该启用GC日志记录,并检查您的OOM在哪里。

    -verbose:gc
    -Xloggc:gc.log  
    -XX:+PrintGCTimeStamps
    -XX:+PrintGCDetails
    

    您可能遇到烫发空间限制,请通过调整 -XX:MaxPermSize=YYYm

    不管怎样,为了回答你的问题,我从没有最小值开始,将最大值设置得相对较高。然后,我绘制GC日志图,找出我的stead状态在哪里;可视化地为各个代选择一个高于平均值的大小。像金融图表一样阅读它,你会希望看到新一代人的良好传播,以及终身一代人的持续增长和收藏。如前所述,还要绘制烫发空间图,以确保不会不断增加。

    GC调优是一门艺术,绝不是一门科学。

        3
  •  3
  •   Pascal Thivent    15 年前

    事实上,盲目地设置一个巨大的最大值并不是一个好主意(测量,不要猜测),而且这种策略将导致非常长的“停止世界”主要GCS,从用户体验的角度来看,这可能是不可取的(始终记住,“堆越大,主要GC越长”)。

    也就是说,对于您的问题没有通用的答案,每个应用程序都有不同的需求。事实上,我建议介绍一下 你的 应用程序并调整堆,以在(主要)GC频率和(主要)GC持续时间之间找到一个很好的折衷方案,同时最小化对最终用户的响应时间。我强烈建议你好好读一读 blog post (和所有其他人)从Kirk Pepperdine了解更多细节。

    为了回答最小值和最大值部分,我总是使用相同的值(为了更好的启动性能和再现性)。

        4
  •  2
  •   Robert Greiner    15 年前

    正确的答案是: 没有正确的答案 每个项目都是不同的,您必须根据每个项目对堆大小配置进行微调。我将从小处开始并逐渐增加堆大小,直到应用程序按预期运行。

    你是对的,设置一个巨大的最大值不是一个好主意。

        5
  •  2
  •   RMorrisey    15 年前

    如果您遇到OOME,我实际上会从尽可能多地增加最大内存开始,看看这是否解决了问题。首先让你的机器吸收性能问题。如果问题仍然存在,那么您可以通过性能诊断来识别瓶颈,并在应用程序可能泄漏或占用大部分内存的区域进行工作。

    Jeff Atwood有一篇关于Coding恐怖的好文章解释了这种态度;解决性能问题的最经济有效的方法是在花费开发人员时间进行故障排除之前,将硬件(或者在这种情况下,增加内存资源)扔到问题上:

    http://www.codinghorror.com/blog/archives/001198.html

        6
  •  2
  •   John    12 年前

    “忽略-xms参数”是一个非常糟糕的主意,因为通常有其他应用程序和进程在同一个框中运行。您希望您的应用程序以分配的最大内存量启动,因此如果它失败,那么在您查看启动日志时它会失败,而不是在凌晨4:00,此时另一个应用程序占用了机箱上的额外内存,并且您的JVM无法增长。

    简而言之,总是将jvm min和mix size设置为相同的值。