【发布时间】:2013-05-17 19:43:16
【问题描述】:
我们通常处理 OutOfMemoryError 问题是因为堆或 permgen 大小配置问题。
但是所有的 JVM 内存都不是 permgen 或 heap。 据我了解,也可以和Threads/Stacks、native JVM code有关……
但是使用 pmap 我可以看到进程分配了 9.3G,即 3.3G 堆外内存使用量。
我想知道监控和调整这种额外的堆外内存消耗的可能性是什么。
我不使用直接堆外内存访问(MaxDirectMemorySize 默认为 64m)
Context: Load testing
Application: Solr/Lucene server
OS: Ubuntu
Thread count: 700
Virtualization: vSphere (run by us, no external hosting)
JVM
java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)
调整
-Xms=6g
-Xms=6g
-XX:MaxPermSize=128m
-XX:-UseGCOverheadLimit
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSClassUnloadingEnabled
-XX:+OptimizeStringConcat
-XX:+UseCompressedStrings
-XX:+UseStringCache
内存映射:
https://gist.github.com/slorber/5629214
vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 1743 381 4 1150 1 1 60 92 2 0 1 0 99 0
免费
total used free shared buffers cached
Mem: 7986 7605 381 0 4 1150
-/+ buffers/cache: 6449 1536
Swap: 4091 1743 2348
热门
top - 11:15:49 up 42 days, 1:34, 2 users, load average: 1.44, 2.11, 2.46
Tasks: 104 total, 1 running, 103 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.5%us, 0.2%sy, 0.0%ni, 98.9%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 8178412k total, 7773356k used, 405056k free, 4200k buffers
Swap: 4190204k total, 1796368k used, 2393836k free, 1179380k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
17833 jmxtrans 20 0 2458m 145m 2488 S 1 1.8 206:56.06 java
1237 logstash 20 0 2503m 142m 2468 S 1 1.8 354:23.19 java
11348 tomcat 20 0 9184m 5.6g 2808 S 1 71.3 642:25.41 java
1 root 20 0 24324 1188 656 S 0 0.0 0:01.52 init
2 root 20 0 0 0 0 S 0 0.0 0:00.26 kthreadd
...
df -> tmpfs
Filesystem 1K-blocks Used Available Use% Mounted on
tmpfs 1635684 272 1635412 1% /run
我们遇到的主要问题:
- 服务器有8G物理内存
- Solr的堆只占用6G
- 有1.5G的swap
- 交换=0
- 似乎适当调整了堆消耗
- 在服务器上运行:只有 Solr 和一些监控的东西
- 我们有正确的平均响应时间
- 我们有时会出现异常长的停顿,最长可达 20 秒
我猜暂停可能是交换堆上的完整 GC 对吧?
为什么会有这么多交换?
我什至不知道这是否是使服务器交换的 JVM,或者它是否是我看不到的隐藏的东西。也许是操作系统页面缓存?但不确定如果创建交换,操作系统为什么会创建页面缓存条目。
我正在考虑测试在一些流行的基于 Java 的存储/NoSQL(如 ElasticSearch、Voldemort 或 Cassandra)中使用的 mlockall 技巧:检查 Make JVM/Solr not swap, using mlockall
编辑:
在这里您可以看到最大堆、已用堆(蓝色)、已用交换(红色)。好像有点关系。
我可以通过 Graphite 看到有很多 ParNew GC 定期发生。并且有一些CMS GC对应图片的heap显着减少。
暂停似乎与堆减少无关,但在 10:00 到 11:30 之间有规律地分布,所以我猜它可能与 ParNew GC 有关。
在负载测试期间,我可以看到一些磁盘活动和一些交换 IO 活动,当测试结束时,这些活动非常平静。
【问题讨论】:
-
该大小中有多少是虚拟内存,有多少是常驻内存?
-
正如 Peter Lawrey 所提到的,主机提供商是否向您保证虚拟机本身始终位于 RAM 中而不是物理换出?
-
为了消除任何疑虑:在我之前对“虚拟机”的评论中,我的意思是“虚拟服务器”==“您的操作系统正在运行的虚拟机”。
-
顺便说一句,您使用 Oracle JVM 还是其他的,例如IBM JVM 还是 JRockit(现在也是 Oracle)?
标签: java performance memory jvm