V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
jaynos
V2EX  ›  问与答

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

  •  
  •   jaynos · 2021-01-22 22:47:08 +08:00 · 1648 次点击
    这是一个创建于 1435 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    求教大佬们解惑,谢谢!

    9 条回复    2021-01-23 14:34:14 +08:00
    XiaoxiaoPu
        1
    XiaoxiaoPu  
       2021-01-22 23:24:03 +08:00
    cat /proc/meminfo 看下。5.0G 只是那一个进程占用的内存,其他进程、内核、硬件都会使用内存的。
    msg7086
        2
    msg7086  
       2021-01-23 00:07:59 +08:00 via Android
    套接字会用内核内存吧,虽然不知道用了多少。
    话说既然跑 Java 了不如内存多给点,我们跑 Java 的小鸡给了 128G 内存基本不担心内存占用的问题。
    nuk
        3
    nuk  
       2021-01-23 00:11:34 +08:00
    还有 slab 呀,都不算在 RES 里面的
    jaynos
        4
    jaynos  
    OP
       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
        5
    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
        6
    XiaoxiaoPu  
       2021-01-23 12:48:44 +08:00
    执行 slabtop 再看看呢?我猜测还是 socket 占用的内存,「就算 1 个 tcp 连接占用 8k 内存,2w 个连接也不过 150M 左右」这个只是粗略估计,每个连接占用的内存是动态的。假如网络数据很多,应用程序从 socket 读取数据之前、socket 把数据发给网卡之前,都要使用内存来暂存的。
    jaynos
        7
    jaynos  
    OP
       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
        8
    jaynos  
    OP
       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
        9
    jaynos  
    OP
       2021-01-23 14:34:14 +08:00
    其实从阿里云监控数据显示,内存占用是逐步上涨的,大概每 5 分钟上涨 0.01%(~0.7m ),所以我最初的调查方向都是以内存泄露为主 [捂脸]
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2781 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 06:59 · PVG 14:59 · LAX 22:59 · JFK 01:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.