监视JVM的非堆内存使用情况

塞巴斯蒂安·洛伯(Sebastien Lorber):

由于堆或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

我们遇到的主要问题是:

  • 服务器具有8G的物理内存
  • Solr的堆仅需6G
  • 有1.5G的掉期
  • Swappiness = 0
  • 堆消耗似乎已适当调整
  • 在服务器上运行:仅Solr和一些监视内容
  • 我们有正确的平均响应时间
  • 有时我们会出现正常的长时间停顿,最多20秒

我猜停顿可能是交换堆上的完整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。

  • 6.0 GB堆。
  • 每秒128 MB
  • 700 MB堆栈。
  • <250个共享库
  • 2.2 GB的未知空间(我怀疑虚拟内存不是驻留内存)

上一次有人遇到此问题时,尽管线程数量多于应有的数量。我将检查您拥有的最大线程数,因为它是确定虚拟大小的峰值。例如接近3000?


嗯,每对都是一个线程。

7f0cffddf000-7f0cffedd000 rw-p 00000000 00:00 0 
7f0cffedd000-7f0cffee0000 ---p 00000000 00:00 0

这些表明您现在的线程数略少于700 .....

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

JVM进程与JVM堆内存使用情况

如何知道点燃非堆内存使用情况?

如何监视内存使用情况?

VisualVM:理想的堆内存使用情况图

C中的多维数组内存使用情况(堆)

在Linux中监视程序的内存使用情况

如何监视Java内存使用情况?

如何监视单个进程的CPU /内存使用情况?

如何监视Node.js的内存使用情况?

监视Java内部对象和内存使用情况

监视CPU和内存使用情况的程序

包含RabbitMQ侦听器的应用程序的内存监视Java堆大小使用情况

如何查看Play框架的JVM内存使用情况

系统监视器中内存使用情况下的缓存使用情况

“ free”命令显示的内存使用情况与系统监视器的使用情况不匹配

与堆使用情况相比,Java应用程序的系统内存使用量巨大

如何使用Java监视计算机的CPU,内存和磁盘使用情况?

如何从命令行检查正在运行的JVM的堆使用情况?

JVM堆使用情况变化。这个图正常吗?

Valgrind 为一个简单的代码检测未释放的堆内存使用情况

获取Linux系统中ac程序的峰值堆内存使用情况

是否可以通过Munin监视Elasticsearch的JVM使用情况?

如何从perfmon监视服务结构微服务和SF服务的内存使用情况

Gnome资源监视器报告的C ++程序中的内存使用情况:混淆

如何在OSX中监视从终端运行的进程的内存使用情况

如何随时间监视进程的内存使用情况-Ubuntu

Google Cloud Platform:如何监视VM实例的内存使用情况

Android Studio中的内存监视器报告的RAM使用情况与设备不同

系统监视器和顶部报告的内存使用情况截然不同