扎实减少66% - 在过去的一年我在我的应用程序的Java堆的使用取得了巨大的改进。 在追求的,我一直在监测各种指标,如Java堆大小,CPU,Java的非堆等通过SNMP。
最近,我一直在监测由JVM多少实际内存(RSS,常驻集),并感到有点惊讶。 由JVM实际消耗的记忆似乎完全独立的我的应用程序堆大小,非堆,伊甸园空间,线程数等。
由Java的SNMP测量堆大小 Java堆用于图形http://lanai.dietpizza.ch/images/jvm-heap-used.png
在KB实内存。 (例如:1 MB,KB = 1 GB)的 Java堆用于图形http://lanai.dietpizza.ch/images/jvm-rss.png
(三个倾角在堆中图表对应于应用程序的更新/重新启动。)
这是我的问题,因为所有这些额外的内存JVM在消费是“偷”,可以通过操作系统的文件缓存使用的内存。 事实上,一旦RSS值达到〜2.5-3GB,我开始看到从我的应用程序较慢的响应时间和更高的CPU利用率,主要是做给IO等待。 由于一些点分页到swap分区踢,这是非常不可取的。
所以,我的问题:
- 这究竟是为什么? 这是怎么回事“引擎盖下”?
- 我能做些什么来保持JVM真实的内存消耗在检查?
血淋淋的细节:
- RHEL4 64位(Linux的 - 2.6.9-78.0.5.ELsmp#1 SMP周三09月24日... 2008 ... x86_64的GNU / Linux的)
- Java 6中(建1.6.0_07-B06)
- Tomcat的6
- 应用程序(按需HTTP视频流)
- 高I / O通过java.nio中FileChannels
- 数百到数千低线程
- 低使用数据库
- spring,hibernate的
有关JVM参数:
-Xms128m
-Xmx640m
-XX:+UseConcMarkSweepGC
-XX:+AlwaysActAsServerClassMachine
-XX:+CMSIncrementalMode
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime
-XX:+CMSLoopWarn
-XX:+HeapDumpOnOutOfMemoryError
如何我衡量RSS:
ps x -o command,rss | grep java | grep latest | cut -b 17-
这正好到一个文本文件,并读入RRD数据库定期我的监控系统。 需要注意的是ps的输出千字节。
存在的问题及解决方案S:
虽然它到底是ATorras的答案被证明最终是正确的,它kdgregory谁引导我与使用的正确诊断路径pmap
。 (去投票了两个自己的答案!)这是发生了什么事:
事情我肯定知道:
- 我的应用程序记录和显示数据与JRobin 1.4 ,这是我在三年前编码到我的应用程序。
- 应用程序的最繁忙的实例:当前创建
- 在1000启动的一个小时内,一些新的JRobin数据库文件(约1.3MB每个)
- 〜100 +在启动后的每一天
- 该应用程序更新这些JRobin数据库对象每隔15秒,如果有东西可写。
- 在默认配置JRobin:
- 使用
java.nio
基于文件访问后端。 这后端映射MappedByteBuffers
到文件本身。 - 每五分钟一次JRobin守护线程调用
MappedByteBuffer.force()
每JRobin基础数据库对MBB
- 使用
-
pmap
所示:- 6500个映射
- 其中5500人1.3MB JRobin数据库文件,其中工程出来〜7.1GB
最后一点是我“找到了!” 时刻。
我纠正措施:
- 考虑更新到这显然是更好的最新JRobinLite 1.5.2
- 在JRobin数据库实施适当的资源处理。 目前,一旦我的应用程序创建一个数据库,然后从不转储数据库的数据库不再积极地使用了。
- 实验与移动
MappedByteBuffer.force()
数据库更新事件,而不是一个周期性的计时器。 将这个问题奇迹般地消失? - 随即 ,改变JRobin后端的java.io执行-线换线。 这会慢一些,但它可能不是一个问题。 这里是在这种变化的直接影响的图表。
Java的RSS内存使用图形http://lanai.dietpizza.ch/images/stackoverflow-rss-problem-fixed.png
我可能会或可能不会有时间问题搞清楚:
- 什么是JVM内部发生的事情与
MappedByteBuffer.force()
如果一切都没有改变,它仍然写整个文件? 该文件的一部分? 它首先加载它? - 有没有在任何时候总是在RSS一定量的MBB的? (RSS大约一半分配MBB尺寸。巧合吗?我怀疑不是总有人。)
- 如果我移动
MappedByteBuffer.force()
数据库更新事件,而不是一个周期定时器,将这个问题奇迹般地消失? - 为什么是RSS坡所以定期? 它不关联到任何应用负载的指标。