You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Current »

问题:某环境发现给定JVM内存为200GB,实际使用量为250GB


复现:尝试在192.168.10.66机器上复现,复现结果是给定JVM内存为100GB,实际使用量为109GB,现对该场景进行分析


已知:总内存 =  java heap + no heap(meta space+code cache 等) + 虚拟机进程本身 + 虚拟机栈(线程栈)*线程数 + native heap(一般说的堆外内存)


分析方法:在项目中添加```-XX:NativeMemoryTracking=detail```JVM参数重启项目,写入5分钟后,使用命令```jcmd pid VM.native_memory detail```查看到的内存分布如下

Total: reserved=109GB, committed=108GB
-                 Java Heap (reserved=100GB, committed=100GB)
                            (mmap: reserved=100GB, committed=100GB)

-                    Thread (reserved=1GB, committed=1GB)
                            (thread #924)
                            (stack: reserved=1GB, committed=1GB)

-                        GC (reserved=4GB, committed=4GB)
                            (mmap: reserved=4GB, committed=4GB)

-                  Internal (reserved=4GB, committed=4GB)
                            (malloc=4GB #17087)

可以看到堆外内存实际占用为4GB,Jprofiler看到的40MB只包含了meta space 和 code space,对我们的分析构成了严重误导!

执行的JAVA指令是:/data/fqx/jdk1.8.0_211/bin/java -Dlogback.configurationFile=./../conf/logback.xml -DIOTDB_HOME=./.. -DTSFILE_HOME=./.. -DIOTDB_CONF=./../conf -DTSFILE_CONF=./../conf -Dname=iotdb\.IoTDB -Xms2048M -Xmx100G -XX:NativeMemoryTracking=detail -Dlogback.configurationFile=./../conf/logback.xml -DIOTDB_HOME=./.. -DTSFILE_HOME=./.. -DIOTDB_CONF=./../conf -DTSFILE_CONF=./../conf -Dname=iotdb\.IoTDB -cp .........


验证方法:为了验证确实是堆外内存导致内存暴涨,我们调整-XX:MaxDirectMemorySize=2G,也就是限制堆外内存最大使用2G,发现内存使用确实下降,但是读写速度有很大的降低(30倍左右),证明IoTDB确实使用了超过2G的堆外内存,如果对堆外内存限制,则性能会有损失,下面是读最大时间的性能截图:

不限制:

限制为2G:


下一步计划:通过加大读写压力使得IoTDB占用内存进一步升高,再次查看堆外内存使用情况,证明堆外内存与读写压力正相关

在如下场景,内存继续升高:

20个存储组 300*8000变量 batch=1000


内存情况如下:

Total: reserved=134GB, committed=132GB
-                 Java Heap (reserved=100GB, committed=99GB)
                            (mmap: reserved=100GB, committed=99GB)

-                    Thread (reserved=1GB, committed=1GB)
                            (thread #834)
                            (stack: reserved=1GB, committed=1GB)

-                        GC (reserved=4GB, committed=4GB)
                            (mmap: reserved=4GB, committed=4GB)

-                  Internal (reserved=29GB, committed=29GB)
                            (malloc=29GB #15358)


已知堆外内存在满了之前都不会主动释放,那么这个堆外内存将会一直增长到阈值(默认与堆内内存一样大),然后才释放,如果没到阈值系统内存就不够了,就会被杀死,具体释放逻辑可以见:https://blog.csdn.net/u013096088/article/details/78774627


最新情况:堆外内存增长到36GB之后就不继续增长了,可能有内部释放机制


  • No labels