我的内存都去哪了 [关于内存占用的问题请教]

2021-01-22 22:47:08 +08:00
 jaynos

请教各位 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 内统计不到堆外内存之类的?

求教大佬们解惑,谢谢!

1507 次点击
所在节点    问与答
9 条回复
XiaoxiaoPu
2021-01-22 23:24:03 +08:00
cat /proc/meminfo 看下。5.0G 只是那一个进程占用的内存,其他进程、内核、硬件都会使用内存的。
msg7086
2021-01-23 00:07:59 +08:00
套接字会用内核内存吧,虽然不知道用了多少。
话说既然跑 Java 了不如内存多给点,我们跑 Java 的小鸡给了 128G 内存基本不担心内存占用的问题。
nuk
2021-01-23 00:11:34 +08:00
还有 slab 呀,都不算在 RES 里面的
jaynos
2021-01-23 01:41:43 +08:00
@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
```
kele1997
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
```
XiaoxiaoPu
2021-01-23 12:48:44 +08:00
执行 slabtop 再看看呢?我猜测还是 socket 占用的内存,「就算 1 个 tcp 连接占用 8k 内存,2w 个连接也不过 150M 左右」这个只是粗略估计,每个连接占用的内存是动态的。假如网络数据很多,应用程序从 socket 读取数据之前、socket 把数据发给网卡之前,都要使用内存来暂存的。
jaynos
2021-01-23 14:18:59 +08:00
@kele1997 #5 可能是我没表达清楚,我的想法是,这台机器只运行了一个 java 程序,在 top 里显示 RES 为 5g,但是 free 里显示已用 6.8g 。然后根据 1 楼所说我去查了相关资料,现学现卖发现还是会有 1g 的内存出入( slab 等加上 5g 之后)

在 free 和 top 里显示的差距应该部分缓存导致的,我想表达的是在 top 或者 free 里看到的内存占用与实际进程相加相差过大的问题
jaynos
2021-01-23 14:28:22 +08:00
@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
```
jaynos
2021-01-23 14:34:14 +08:00
其实从阿里云监控数据显示,内存占用是逐步上涨的,大概每 5 分钟上涨 0.01%(~0.7m ),所以我最初的调查方向都是以内存泄露为主 [捂脸]

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/747560

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX