【问题标题】:Heap Memory default allocation in CassandraCassandra 中的堆内存默认分配
【发布时间】:2019-12-29 03:28:06
【问题描述】:

根据 cassandra-env.sh,440G 总 RAM 的默认堆内存分配应为 32765M(JVM 切换到 64 位参考之前的最大 CAP)。

那么,为什么当我查询“java -XX:+PrintCommandLineFlags -version”或“java -XX:+PrintFlagsFinal -version | grep -iE 'MaxHeapSize'”时它显示 32210157568 字节(30718M)

为什么会有差异,2G左右。

仅供参考:jvm.options 文件是默认文件并使用 DSE 5.1.3。

【问题讨论】:

    标签: cassandra jvm datastax


    【解决方案1】:

    java -XX:+PrintFlagsFinal与Cassandra无关,我也不知道你为什么提到cassandra-env.sh。无论如何,让我回答问题的主要部分。

    在JDK 8中,当-Xmx没有指定时,最大堆大小估计为

    MaxHeapSize = min(1/4 RAM, max_heap_for_compressed_oops)
    

    在您的情况下,服务器具有大量 RAM,因此默认堆大小受到从零开始的压缩 oop 支持的最大可能大小的限制,即 32 GB。

    堆显然不能从零地址开始(空页被操作系统保留),而default heap alignment是2 MB,所以我们必须至少减去2 MB。

    然后,JDK 更喜欢在 HeapBaseMinAddress 分配堆,在 Linux 上是 equal to 2 GB。这提供了一些空间来增长进程的本机堆。出于这个原因,JVM reduces 的默认最大堆大小为HeapBaseMinAddress

    这就是为什么最终计算的堆大小等于

    32 GB - 2 MB - 2 GB = 32210157568
    

    如果您放弃对从零开始的压缩 oops 的要求,您可以设置-XX:HeapBaseMinAddress=0。在这种情况下,计算的堆大小将是

    32 GB - 2MB = 32766 MB
    

    【讨论】:

    • 我之所以使用 Cassandra,是因为 Cassandra 在 JVM 下运行,所以有一个名为 cassandra-env.sh 的文件,上面写着,MAX_HEAP_SIZE 是根据“max(min(1/2 ram, 1024MB) ), min(1/4 ram, 32GB))”和一条评论说“# cap here to 32765M because the JVM switch to 64 bit references at 32767M”并指向链接“java-performance.info/over-32g-heap-java
    • @apangin 为什么当它的起始地址不在零地址附近时,堆大小仍然减去 2MB?
    • @Pramod 显然cassandra-env.sh 中的评论是错误的(至少对于现代 JDK 版本)。您可以在issues.apache.org/jira/projects/CASSANDRA 提交问题
    • @Holger 计算限制的代码只是将空页面first 打折,并调整HeapBaseMinAddress afterwards 的大小。你是对的,它不需要这样,但这样的优化无论如何也没有多大价值。
    • @apangin 好吧,是的,在这种情况下它并没有带走太多东西。但每当我在 JVM 中看到如此短视的代码时,我都会感到有些惊讶。例如,负责数组大小限制的代码真的很奇怪,甚至没有理由证明它的存在……
    猜你喜欢
    • 2014-12-12
    • 2011-10-09
    • 2021-04-08
    • 2019-11-24
    • 2012-12-05
    • 2011-05-28
    • 2018-07-24
    • 1970-01-01
    相关资源
    最近更新 更多