Sun JVM可以毫无问题地处理巨大的堆大小,以及如何处理?

时间:2009-11-08 10:56:20

标签: java garbage-collection jvm heap performance

我听过几个人声称你无法扩展JVM堆大小。我听说过实际限制是4千兆字节(我听说IBM顾问这么说),10千兆字节,32千兆字节等等...我简直无法相信这些数字并且一直在想这个问题现在有一段时间了。

所以,我有三个问题我希望有经验的人能回答:

  1. 鉴于以下情况,您将如何调整堆和GC设置?
  2. 终端用户会注意到会有明显的hickup(JVM暂停等)吗?
  3. 这真的还能用吗?我认为应该。
  4. 案例:

    • 64位平台
    • 64核
    • 64千兆字节的内存
    • 应用程序服务器面向客户端(即Jboss / tomcat Web应用程序服务器) - 最终用户可能会注意到JVM的完整暂停
    • Sun JVM,可能是1.5

    为了证明我不是要求你们做我的作业,这就是我想出的:

    1. -XX:+UseConcMarkSweepGC -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:-EliminateZeroing -Xmn768m -Xmx55000m
    2. CMS应该减少暂停量,尽管它会带来开销。 CMS的其他设置似乎自动默认为CPU数量,因此它们对我来说似乎是理智的。我添加的其余内容是可能在性能方面做得好或坏的额外内容,它们应该进行测试。
    3. 肯定。

7 个答案:

答案 0 :(得分:9)

我认为,如果不进一步了解您的申请,任何人都很难给予您一般建议。

我建议您使用VisualGC(或VisualVM的VisualGC插件)实际查看,了解当您的应用运行时垃圾收集正在执行的操作。一旦您对GC与应用程序的工作方式有了更深入的了解,就可以更容易地对其进行调整。

答案 1 :(得分:9)

  

#1。鉴于以下情况,您将如何调整堆和GC设置?

首先,拥有64千兆字节的内存并不意味着您必须将它们全部用于一个JVM。实际上,它意味着你可以运行其中许多。然后,如果没有任何访问您的机器和应用程序的测量并分析事物(知道您的应用程序正在做什么是不够的),则无法回答您的问题。不,我不是要求访问您的环境:))

  

#2。是否会有最终用户注意到的明显的hickup(JVM暂停等)?

调整的目标是在(主要)GC的频率和持续时间之间找到一个很好的折衷方案。使用~55g堆时,GC不会频繁,但肯定会有明显的时间(堆越大,主GC越长)。使用并行或并发垃圾收集器将有助于多处理器系统,但不会完全解决此问题。为什么你需要~55g(对于一个webapp IMO来说这是超级巨大的),这是我的问题。如果需要,我宁愿运行许多集群JVM来处理负载(在某些时候,数据库将成为数据导向应用程序的瓶颈)。

  

#3。这真的还能用吗?我认为应该。

嗯......不确定我是否得到了这个问题。什么是“ this ”?使用大堆实例化JVM?是的,它应该。它等同于运行多个JVM吗?不,当然不是。

PS:4G是在64位操作系统上运行的32位JVM的最大理论堆限制(请参阅Why can't I get a larger heap with the 32-bit JVM?

PPS:在64位VM上,您可以使用64位可寻址性,从而导致最大Java堆大小仅受系统提供的物理内存和交换空间量的限制。 (见How large a heap can I create using a 64-bit VM?

答案 2 :(得分:3)

显然堆大小不是无限制的,堆大小越大,JVM最终将花费在GC上的越多。虽然我认为可以在64位JVM上设置相当高的堆大小,但我仍然认为它并不实用。这里的建议最好是让几个JVM以相同的参数运行,即在同一物理机器上运行的JBoss / Tomcat节点集群,你将获得更好的吞吐量。

编辑:您的GC行为也取决于您的堆的分类。如果你有很多短生命对象,并且每个请求到服务器创建了很多这些对象,那么你的GC会经常收集大量垃圾,因此在大堆大小时会导致更长的暂停。如果你有很多长寿命的对象(例如在内存中缓存大部分数据)并且短生命对象的数量不是那么大,那么拥有更大的堆大小就没问题。

答案 3 :(得分:3)

正如Chris Rice已经写过的那样,我不希望GC的堆大小高达32-64GB有任何明显的问题,尽管你的应用程序逻辑当然可能存在某些问题,这可能会导致问题。

与GC没有直接关系,但我仍然建议您在生产系统上执行实际的负载测试。我曾经在一个项目上工作,我们有一个类似的设置(相对较大的,集群JBoss / Tomcat设置来服务公共Web应用程序)并且毫不夸张地说,JBoss在高负载或大量并发时表现不佳如果您正在使用EJB,则调用。在访问和管理EJB实例池时,JBoss在同步块中花费了大量时间,如果您选择群集,它甚至会等待这些同步块内的群集内网络通信。如果您正在使用SFSB,请特别注意性能不佳的状态复制。

答案 4 :(得分:3)

仅添加一些我默认使用的开关:-Xms55g可以帮助减少加速时间,因为它可以使Java免于检查它是否可以回退到初始大小并允许更好的内部初始大小调整记忆区域。

此外,我们使用NewSize为您提供了一个很大的年轻尺寸来摆脱短期垃圾:-XX:NewSize = 1g此外,大多数Web应用程序创建了大量的短时间垃圾,这些垃圾永远不会在请求处理中存活下来。你甚至可以做得更大。使用Xms55g,VM已经保留了很大的块。也许瘦身会有所帮助。

-Xincgc有助于逐步清理年轻代,并经常将cpu返回给用户线程。

-XX:CMSInitiatingOccupancyFraction = 70如果您真的填满了所有内存,请尝试更早地启动CMS垃圾回收。

-XX:+ CMSIncrementalMode将CMS置于增量模式,以便更频繁地将cpu返回给用户线程。

使用jstat -gc -h 10 <pid> 1s附加到流程,并观察GC的工作情况。

你真的会填满记忆吗?我假设64cpus用于请求处理甚至可以使用更少的内存。你在那里存放什么?

答案 5 :(得分:2)

根据您的GC暂停分析,您可能希望实施Incremental模式,以便在一段时间内暂停长暂停。

答案 6 :(得分:1)

我发现内存架构在大内存中起着重要作用。如果应用程序使用多个内存条,则一般情况下执行效果不佳。 JVM似乎也受到影响,特别是必须扫描整个内存的GC。

如果您的应用程序不适合一个内存条,则您的应用程序必须拉入非处理器本地的内存,并使用另一个处理器本地的内存。

在linux上,您可以运行numactl --hardware来查看处理器和内存条的布局。