[转帖]某游戏海外版本堆外内存泄露排查

游戏,海外,版本,内存,泄露,排查 · 浏览次数 : 0

小编点评

**问题分析:** * 一部分服务器的 Java 进程内存占用占比达到 99%,其中有一台服务器被 Linux OOM Kill 排查选择了 110 个服,其 Java 进程最大堆内存设置为 9710m,但进程占用的 RES却达到了 14g,远比堆内存大很多。 **可能的堆外内存泄露原因:** * 由于 `libunwind1. libunwind` 库默认安装在 `/usr/local/lib2`,可能存在内存泄露问题,导致 Java 进程无法释放内存。 **排查步骤:** 1. 使用 `ldconfig` 命令在 `/etc/ld.so.conf.d` 中添加 `LD_PRELOAD=/usr/local/lib/libtcmalloc.so` 选项,以覆盖默认安装路径。 2. 使用 `HEAPPROFILE=/tmp/nonheapleak` 选项设置堆外内存收集文件路径。 3. 使用 `pgrep` 等工具监控 Java 进程,并在 `nonheapleak_XX` 文件中找到泄露的进程 ID。 4. 使用 `jmap` 等工具分析内存泄露文件,例如 `nonheapleak_31733.0089.heap`。 5. 分析内存泄露文件,确定哪些对象导致了内存占用。 6. 与客户端同学一起排查,确定泄露的具体原因。 **解决思路:** * 尝试禁用 `libunwind` 库,并将 `LD_PRELOAD` 和 `HEAPPROFILE` 设置为默认值。 * 确保 `libtcmalloc.so` 是 Java 进程使用的正确版本。 * 使用 `-XX:MaxDirectMemorySize` 参数设置 `DirectByteBuffer` 的最大分配大小。 * 仔细分析内存泄露文件,确定哪些对象导致了内存占用。 * 与客户端同学一起调试代码,确定泄露的原因。

正文

https://www.jianshu.com/p/cae00d9c99fe

 

某游戏海外版本堆外内存泄露排查

  1. 现象

    • 线上有部分服务器用top发现Java进程内存占用占比达到99,而且出现了有一个服务器被Linux OOM Kill
  2. 排查

    • 选择了110服,该机器的Java进程最大堆内存设置的是9710m,但是进程占用的RES却达到了14g,远比堆内存大很多,所以初步确认,一定是出现了堆外内存泄露
  3. 工具安装

    • 堆外内存泄露的工具通常是gperftools

    • 同时要安装libunwind

      1. libunwind默认安装在/usr/local/lib
      2. 需要root在/etc/ld.so.conf.d建一个usr_local_lib.conf,文件内容是/usr/local/lib/
      3. 然后使用ldconfig命令刷一下
      
    • java进程启动脚本增加参数

      export LD_PRELOAD=/usr/local/lib/libtcmalloc.so
      export HEAPPROFILE=/tmp/nonheapleak
      
    • 注:

  4. 定位

    • 启动后,在/tmp目录会每隔一段时间都会生成如nonheapleak_31733.0088.heap、nonheapleak_31733.0089.heap等文件

    • 使用如下命令分析

      $ pprof --text ~/kof/usr/jdk/bin/java nonheapleak_31733.0089.heap | less

    • 输出

      Using local file /opt/home/service/kof/usr/jdk/bin/java.
      Using local file nonheapleak_31733.0089.heap.
      Total: 1509.3 MB
        1293.1  85.7%  85.7%   1293.1  85.7% luaM_realloc_
         179.4  11.9%  97.6%    179.4  11.9% os::malloc
          30.0   2.0%  99.5%     30.0   2.0% init
           2.4   0.2%  99.7%      2.4   0.2% updatewindow
           1.2   0.1%  99.8%      1.2   0.1% strbuf_resize
           1.2   0.1%  99.9%      1.2   0.1% ObjectSynchronizer::omAlloc
           1.0   0.1%  99.9%      1.0   0.1% inflateInit2_
      
    • 从上面可以看到luaM_realloc_占用了较大内存,初步判断堆外内存占用这块主要是lua

    • 所以下面的排查和解决思路是

      为什么lua占用了这么大的内存

      是否有泄露的可能

      需要客户端同学一起排查,一个gc后的luastate到底内存都有哪些对象

      是否关闭本地复盘,因为有潜在的oom-kill的风险

  5. 其他

    • -XX:MaxDirectMemorySize=size用于设置New I/O(java.nio) direct-buffer allocations的最大大小,即这个主要是nio相关,即狭义的‘堆外内存’。而Direct ByteBuffer分配出去的直接内存其实也是由GC负责回收的
    • 而本例是指jni分配的内存导致的内存泄露,这个是无法被jvm回收的
  6. ref

与[转帖]某游戏海外版本堆外内存泄露排查相似的内容:

[转帖]某游戏海外版本堆外内存泄露排查

https://www.jianshu.com/p/cae00d9c99fe 某游戏海外版本堆外内存泄露排查 现象 线上有部分服务器用top发现Java进程内存占用占比达到99,而且出现了有一个服务器被Linux OOM Kill 排查 选择了110服,该机器的Java进程最大堆内存设置的是9710

[转帖]awk提取某一行某一列的数据

https://www.jianshu.com/p/dbcb7fe2da56 1、提取文件中第1列数据 awk '{print $1}' filename > out.txt 2、提取前2列的文件 awk `{print $1,$2}' filename > out.txt 3、打印完第一列,然后打

[转帖]限制内核 udp bad checksum 失败告警信息

问题描述 某系统 dmesg 信息中有如下内容频繁打印,冲掉了其它相关的信息,需要限制打印。 UDP: bad checksum. From 10.66.245.93:61525 to 255.255.255.255:137 ulen 58 相关代码 内核源码树中的文件名: net/ipv4/udp

[转帖]TIKV扩容之刨坑填坑​

01 背景 某tidb集群收到告警,TIKV 节点磁盘使用率85%以上,联系业务无法快速删除数据,于是想到扩容TIKV 节点,原先TIKV 节点机器都是6TB的硬盘,目前只有3TB的机器可扩,也担心region 均衡后会不会打满3TB的盘,PD 调度策略来看应该是会根据不同存储机器的资源配置和使用情

[转帖]ESXi主机网卡识别为10Mb导致业务缓慢

某企业所有业务系统及应用运行在由5台安装了ESXi 6.0的服务器组成的虚拟化环境中,已经稳定运行了多年,基本上没有出过问题。 今天下午企业工程师联系我,说单位的业务系统访问很慢。在业务系统中PING网关的延时超过2ms,平常都是小于1ms。近期单位服务器与网络没有改动。 检查发现有台物理主机内存报

[转帖]Intel关NUMA的内存编址

https://zhuanlan.zhihu.com/p/454928730 最近在做某国产化平台相关的适配, 不管NUMA的性能和实现方式都和Intel有较大不同, 作为比较对象, 理解Intel的NUMA实现是很有必要的. 虽然从软件角度, 打开NUMA会带来额外的复杂度, 但是从硬件角度, 关

[转帖]使用Linux命令快速查看某一行

原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 当年,我还是Linux菜鸟的时候,就在简历上写着精通Linux命令了,而当面试官问我“如何快速查看某个文件的第200行,仅这一行”时,我的心里是懵逼的。 当时面试官心里估计在窃喜,从我敷衍的回答中,他应该已经完全

[转帖]记一次vcsa6修复过程

一、 某天发现一台vmware vCenter Server Appliance services 6偶尔能登陆了,但极不稳定,连shell都偶尔能进...... 然后利用各种手段想方设法进到shell里,这是必须的,否则白谈.... 首先查看空间:df -h,发现/和/storage/log都用了

[转帖]PostgreSQL 统计所有数据表各自的总行数

一般来说,可以使用 count(*) 来获取具体某张表的总行数: SELECT count(0) FROM t_user; 如果想获得所有表的行数信息,可以使用以下 SQL 语句: SELECT relname, reltuplesFROM pg_class CLS LEFT JOIN pg_nam

[转帖]为什么说MySQL单表行数不要超过2000w?

https://segmentfault.com/a/1190000042716913 大家好,我是不才陈某~ 作为在后端圈开车的多年老司机,是不是经常听到过,“mysql 单表最好不要超过 2000w”,“单表超过 2000w 就要考虑数据迁移了”,“你这个表数据都马上要到 2000w 了,难怪查