请教各位 linux/java 大佬们一个关于内存占用的问题。
先说下场景是一个 springboot + websocket-starter 的即时任务服务。单机 4c8g 只运行该服务,大概维持 2w+长连接。free -h 显示内存占用为 6.8G 。在 top 中显示该进程 RES 为 5.0G 。阿里云后台报警显示已经占用了 95%+的内存。
以下为 free -h 命令输出结果
[root@develop srv]# free -h
              total        used        free      shared  buff/cache   available
Mem:           7.4G        6.8G        223M        536K        321M        297M
Swap:            0B          0B          0B
以下为 top 命令按内存排序部分输出结果
top - 22:40:13 up 14 days,  5:36,  2 users,  load average: 0.22, 0.18, 0.21
Tasks:  97 total,   1 running,  96 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.0 us,  1.2 sy,  0.0 ni, 94.5 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem :   7551.8 total,    220.8 free,   7008.6 used,    322.3 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.    295.5 avail Mem 
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                
22739 root      20   0 8646580   5.0g  14500 S  23.3 68.2   1485:21 java                                                                                                   
 1563 root      20   0 1005204  13264   2308 S   0.3  0.2  64:57.91 /usr/local/clou                                                                                        
  859 root      20   0  574296  11484    188 S   0.0  0.1   1:33.52 tuned                                                                                                  
  380 root      20   0   47652  10988  10636 S   0.0  0.1   0:03.24 systemd-journal
我的疑问是这两个数据到底是怎么算的 [捂脸] ,为啥 free 显示占用 6.8G ,但是 top 里只看到 5.0G 的内存占用。
目前有点怀疑是否是内存泄露导致?还是因为 top 内统计不到堆外内存之类的?
求教大佬们解惑,谢谢!
|  |      1XiaoxiaoPu      2021-01-22 23:24:03 +08:00 cat /proc/meminfo 看下。5.0G 只是那一个进程占用的内存,其他进程、内核、硬件都会使用内存的。 | 
|  |      2msg7086      2021-01-23 00:07:59 +08:00 via Android 套接字会用内核内存吧,虽然不知道用了多少。 话说既然跑 Java 了不如内存多给点,我们跑 Java 的小鸡给了 128G 内存基本不担心内存占用的问题。 | 
|  |      3nuk      2021-01-23 00:11:34 +08:00 还有 slab 呀,都不算在 RES 里面的 | 
|  |      4awm47 OP @XiaoxiaoPu @nuk  感谢,学到了新知识!根据 http://linuxperf.com/?p=142 这篇文章所说,我计算了下 meminfo 里的统计数据,还是有些会对不上,按文章所说,差的大概 1g 内存可能是因为 alloc_pages/__get_free_page 分配的? @msg7086 根据 https://zhuanlan.zhihu.com/p/25241630 这篇文章,就算 1 个 tcp 连接占用 8k 内存,2w 个连接也不过 150M 左右 [捂脸] 我有点疑惑的是不知道堆外内存会不会被统计到 RES 中,因为从网上一些内存泄露的排查过程中有提到 zip 压缩的问题( https://www.cnblogs.com/aipaojiao/p/13680207.html ),而在实际项目中是有用到 websocket 的 permessage-deflate 扩展的( https://tools.ietf.org/html/rfc7692 ) ```plain // 去掉了为 0KB 的字段 MemTotal: 7733012 kB // 7551.78M MemFree: 215988 kB // 210.93M MemAvailable: 280524 kB // 273.95M Buffers: 28368 kB // 27.70M Cached: 225080 kB // 219.80M Active: 5467844 kB // 5339.60M Inactive: 111284 kB // 108.68M Active(anon): 5325980 kB // 5201.15M Inactive(anon): 236 kB // 0.23M Active(file): 141864 kB // 138.54M Inactive(file): 111048 kB // 108.45M Dirty: 440 kB // 0.43M AnonPages: 5325680 kB // 5200.86M Mapped: 46940 kB // 45.84M Shmem: 536 kB // 0.52M Slab: 143460 kB // 140.10M SReclaimable: 64056 kB // 62.55M SUnreclaim: 79404 kB // 77.54M KernelStack: 6816 kB // 6.66M PageTables: 15420 kB // 15.06M CommitLimit: 3866504 kB // 3775.88M Committed_AS: 5697572 kB // 5564.04M VmallocTotal: 34359738367 kB // 32768G VmallocUsed: 20152 kB // 19.68M VmallocChunk: 34359712252 kB // 32767.98G Percpu: 704 kB // 0.69M AnonHugePages: 4769792 kB // 4658M HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB // 2M DirectMap4k: 66232 kB // 64.68M DirectMap2M: 3848192 kB // 3758M DirectMap1G: 4194304 kB // 4096M ``` | 
|  |      5kele1997      2021-01-23 11:42:51 +08:00 你应该再看看 1 楼说,你的 top 那个 5G 是 java 单个程序的占用的内存     top 显示占用的内存是 7008.6 MB, 而 free -h 看到了只有 6.8G ,这么看来两者相差 200MB 左右。。 根本就没有相差 1g 内存 ``` MiB Mem : 7551.8 total, 220.8 free, 7008.6 used, 322.3 buff/cache ``` | 
|  |      6XiaoxiaoPu      2021-01-23 12:48:44 +08:00 执行 slabtop 再看看呢?我猜测还是 socket 占用的内存,「就算 1 个 tcp 连接占用 8k 内存,2w 个连接也不过 150M 左右」这个只是粗略估计,每个连接占用的内存是动态的。假如网络数据很多,应用程序从 socket 读取数据之前、socket 把数据发给网卡之前,都要使用内存来暂存的。 | 
|  |      7awm47 OP @kele1997 #5 可能是我没表达清楚,我的想法是,这台机器只运行了一个 java 程序,在 top 里显示 RES 为 5g,但是 free 里显示已用 6.8g 。然后根据 1 楼所说我去查了相关资料,现学现卖发现还是会有 1g 的内存出入( slab 等加上 5g 之后) 在 free 和 top 里显示的差距应该部分缓存导致的,我想表达的是在 top 或者 free 里看到的内存占用与实际进程相加相差过大的问题 | 
|  |      8awm47 OP @XiaoxiaoPu #6 嗯哈,昨晚我也看到了 https@@@zhuanlan.zhihu.com/p/25241630 这篇文章里的讲解,结合我的实际情况(绝大多数是每隔 20s 的 ping/pong 心跳,服务端直接响应 pong,不做任何处理)考虑,我觉得 socket 应该不会暂存这么多的数据。昨晚升级了服务器,现场数据已经没了 [捂脸] ,不过今天看了下,大致是能对的上了。以下是 slabtop 的数据,看起来 socket 其实也没有那么大? ```plain Active / Total Objects (% used) : 381214 / 384110 (99.2%) Active / Total Slabs (% used) : 14068 / 14068 (100.0%) Active / Total Caches (% used) : 73 / 101 (72.3%) Active / Total Size (% used) : 136913.44K / 137986.20K (99.2%) Minimum / Average / Maximum Object : 0.01K / 0.36K / 8.00K OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 75054 74990 99% 0.19K 3574 21 14296K dentry 46956 46956 100% 0.10K 1204 39 4816K buffer_head 32832 32553 99% 0.06K 513 64 2052K kmalloc-64 23472 23296 99% 0.66K 978 24 15648K proc_inode_cache 21808 21455 98% 0.25K 1363 16 5452K kmalloc-256 21392 21261 99% 0.07K 382 56 1528K avc_node 21024 20410 97% 0.12K 657 32 2628K kmalloc-128 19900 19713 99% 0.62K 796 25 12736K sock_inode_cache 19710 19513 99% 2.06K 1314 15 42048K TCPv6 16286 16286 100% 0.12K 479 34 1916K kernfs_node_cache 14283 14283 100% 0.58K 529 27 8464K inode_cache 11744 11744 100% 1.00K 734 16 11744K ext4_inode_cache 11424 11424 100% 0.04K 112 102 448K selinux_inode_security 5418 5418 100% 0.21K 301 18 1204K vm_area_struct 4864 4864 100% 0.02K 19 256 76K kmalloc-16 4096 4096 100% 0.01K 8 512 32K kmalloc-8 3500 3500 100% 0.57K 125 28 2000K radix_tree_node 3366 2613 77% 0.08K 66 51 264K anon_vma 3315 3315 100% 0.05K 39 85 156K shared_policy_node 3264 3264 100% 0.04K 32 102 128K ext4_extent_status 1792 1792 100% 0.03K 14 128 56K kmalloc-32 1785 1785 100% 0.19K 85 21 340K kmalloc-192 1722 1722 100% 0.09K 41 42 164K kmalloc-96 1584 1584 100% 1.00K 99 16 1584K kmalloc-1024 1184 1079 91% 0.50K 74 16 592K kmalloc-512 1080 1080 100% 0.11K 30 36 120K jbd2_journal_head 912 912 100% 0.66K 38 24 608K shmem_inode_cache 680 680 100% 0.02K 4 170 16K fsnotify_mark_connector 567 567 100% 0.19K 27 21 108K cred_jar 544 544 100% 0.12K 17 32 68K pid 540 540 100% 0.11K 15 36 60K task_delay_info ``` | 
|  |      9awm47 OP 其实从阿里云监控数据显示,内存占用是逐步上涨的,大概每 5 分钟上涨 0.01%(~0.7m ),所以我最初的调查方向都是以内存泄露为主 [捂脸]  |