由于堆或permgen大小配置问题,我们通常会处理OutOfMemoryError问题。
但是所有的JVM内存都不是permgen或堆。据我了解,它也可能与线程/堆栈,本地JVM代码有关...
但是使用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)
虚拟机
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
虚拟机
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
我们遇到的主要问题是:
我猜停顿可能是交换堆上的完整GC,对吧?
为什么会有这么多交换?
我什至不真正知道这是使服务器交换的JVM,还是我看不到的隐藏东西。也许操作系统页面缓存?但是不确定如果创建交换,操作系统为什么会创建页面缓存条目。
我正在考虑测试mlockall
一些流行的基于Java的存储/ NoSQL(例如ElasticSearch,Voldemort或Cassandra )中使用的技巧:使用mlockall检查使JVM / Solr不交换
编辑:
在这里,您可以看到最大堆,已用堆(蓝色),已用交换(红色)。似乎有点相关。
我可以通过Graphite看到有很多ParNew GC定期发生。并且有一些CMS GC对应于图片的堆显着减少。
暂停似乎与堆的减少无关,而是在10:00到11:30之间有规律地分布,所以我想它可能与ParNew GC有关。
在负载测试期间,我可以看到一些磁盘活动以及一些交换IO活动,这些活动在测试结束时非常稳定。
您的堆实际上正在使用6.5 GB的虚拟内存(这可能包括perm gen)
您有一堆使用64 MB堆栈的线程。不清楚为什么会这样,而其他人正在使用默认的1 MB。
总计为930万KB的虚拟内存。我只担心居民人数。
尝试使用top
查找进程的驻留大小。
您可能会发现此程序很有用
BufferedReader br = new BufferedReader(new FileReader("C:/dev/gistfile1.txt"));
long total = 0;
for(String line; (line = br.readLine())!= null;) {
String[] parts = line.split("[- ]");
long start = new BigInteger(parts[0], 16).longValue();
long end = new BigInteger(parts[1], 16).longValue();
long size = end - start + 1;
if (size > 1000000)
System.out.printf("%,d : %s%n", size, line);
total += size;
}
System.out.println("total: " + total/1024);
除非您有使用内存的JNI库,否则我猜您是有很多线程,每个线程都有自己的堆栈空间。我将检查您拥有的线程数。您可以减少每个线程的最大堆栈空间,但是更好的选择可能是减少线程数量。
根据定义,堆外内存是不受管理的,因此不容易对其进行“调整”。甚至调整堆都不简单。
64位JVM的默认堆栈大小为1024K,因此700个线程将使用700 MB的虚拟内存。
您不应将虚拟内存大小与常驻内存大小混淆。64位应用程序上的虚拟内存几乎是免费的,这只是您应该担心的驻留大小。
从我的角度来看,您总共有9.3 GB。
上一次有人遇到此问题时,尽管线程数量多于应有的数量。我将检查您拥有的最大线程数,因为它是确定虚拟大小的峰值。例如接近3000?
嗯,每对都是一个线程。
7f0cffddf000-7f0cffedd000 rw-p 00000000 00:00 0
7f0cffedd000-7f0cffee0000 ---p 00000000 00:00 0
这些表明您现在的线程数略少于700 .....
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句