KOOM(高性能线上内存监控方案

KOOM介绍
OOMMonitor 介绍
KOOM线上APM监控最全剖析
一文看懂快手KOOM高性能监控方案
KOOM 浅析
【开源库剖析】KOOM V1.0.5 源码解析

目录
KOOM 功能
1. Java Heap 泄漏监控
1.1 OOMMonitor 介绍
1.2 OOMMonitor 适用范围
1.3 OOMMonitor 接入
2. Native Heap 泄漏监控
2.1 LeakMonitor 介绍
2.2 LeakMonitor 适用范围
2.3 LeakMonitor 接入
3. Thread 泄漏监控
3.1 ThreadLeakMonitor 介绍
3.2 ThreadLeakMonitor 适用范围
3.3 ThreadLeakMonitor 接入

  KOOM(Kwai OOM, Kill OOM)是快手性能优化团队在处理移动端OOM问题的过程中沉淀出的一套完整解决方案。
KOOM 功能
Koom流程:

在这里插入图片描述

 

OOM问题原因分类

Java堆内存溢出
无足够连续内存空间
FD(文件描述符)超出限制
线程数量超出限制
虚拟内存不足


1. Java Heap 泄漏监控
  

koom-java-leak 模块用于 Java Heap 泄漏监控:它利用 Copy-on-write 机制 fork 子进程 dump Java Heap,解决了 dump 过程中 app 长时间冻结的问题

fork子进程去执行dumpHprofData方法
fork进程采用的是“Copy On Write”技术,只有在进行写入操作时,才会为子进程拷贝分配独立的内存空间,默认情况下,子进程可以和父进程共享同个内存空间,所以,当我们要执行dumpHprofData方法时,可以先fork一个子进程,它拥有父进程的内存副本,然后在子进程中执行dumpHprofData方法,而父进程则可以正常继续运行。

在这里插入图片描述

 

  hprof是基于JVMTI实现的内存分析器代理,其转储文件记录了Java的内存镜像(Heap Profile),其中记录了内存堆详细的使用信息,可用于分析Java程序内存的各种性能问题。
  虚拟机提供的Debug.dumpHprofData可以将hprof文件输出在指定的文件中,但是这个过程会“冻结”整个应用进程,造成数秒甚至数十秒内用户无法操作,即dump文件也是会产生STW(Stop the world),跟GC一样会让所有线程挂起。

public boolean isTrigger() {
    if (!started) {
      return false;
    }

    HeapStatus heapStatus = currentHeapStatus();

    if (heapStatus.isOverMaxThreshold) {
      // 已达到最大阀值,强制触发trigger,防止后续出现大内存分配导致OOM进程Crash,无法触发trigger
      KLog.i(TAG, "heap used is over max ratio, force trigger and over times reset to 0");
      currentTimes = 0;
      return true;
    }

    if (heapStatus.isOverThreshold) {
      KLog.i(TAG, "heap status used:" + heapStatus.used / KConstants.Bytes.MB
              + ", max:" + heapStatus.max / KConstants.Bytes.MB
              + ", last over times:" + currentTimes);
      if (heapThreshold.ascending()) {
      	// 第一次进来 或者 当前内存占用率跟上次高 或者 当前内存占用率超过了最大的阈值(95%)
        if (lastHeapStatus == null || heapStatus.used >= lastHeapStatus.used || heapStatus.isOverMaxThreshold) {
          currentTimes++;
        } else {
          KLog.i(TAG, "heap status used is not ascending, and over times reset to 0");
          currentTimes = 0;
        }
      } else {
        currentTimes++;
      }
    } else {
      currentTimes = 0;
    }

    lastHeapStatus = heapStatus;
    return currentTimes >= heapThreshold.overTimes();
  }



Koom中设置了五种检测器
① HeapOOMTracker
② ThreadOOMTracker
③ FdOOMTracker
④ PhysicalMemoryOOMTracker
⑤ FastHugeMemoryOOMTracker
前三种称为长期高内存检测器,检测机制是当计算出内存占用率之后,我们看下面的一个判断条件,如果内存占用率超过我们设定的一个阈值(例如0.8),而且当前内存占用率跟上次比较超过了千分之5,那么mOverThresholdCount变量就会自增1。

Heap监测机制是第一次进来 或者 当前内存占用率跟上次高 或者
当前内存占用率超过了最大的阈值(95%),三个条件只要满足一个,那么mOverThresholdCount变量就会自增1

  因为检测是一个循环的过程,所以当第一次进来的时候,一定会自增1,而且会将本次的内存占用率赋值给mLastHeapRatio,当下次进来的时候,如果内存占用率较上次降低了,那么就会重置。
  如此往复,当mOverThresholdCount超出我们设置的阈值(例如3次),我们就认定系统发生了内存泄漏,这个时候就需要告警,并dump内存快照分析问题。
即 1)内存占用超过80%,2)并且检测到了3次,两个条件同时满足就会进行dump。
第四种代码中返回false没有进行处理。
第五种称为高危内存与快速增长检测器,检测机制是内存占用超过90%或者本次检测与上次检测内存占用超过350M,满足两个条件之一就会进行dump。

1.1 OOMMonitor 介绍

用于监控应用的 Java 内存泄漏问题,它的核心原理:

周期性查询Java堆内存、线程数、文件描述符数等资源占用情况,当连续多次超过设定阈值或突发性连续快速突破高阈值时,触发镜像采集
镜像采集采用虚拟机supend->fork虚拟机进程->虚拟机resume->dump内存镜像的策略,将传统Dump冻结进程20s的时间缩减至20ms以内
基于shark执行镜像解析,并针对shark做了一系列调整用于提升性能,在手机设备测即可执行离线内存泄露判定与引用链查找,生成分析报告

1.2 OOMMonitor 适用范围

Android L 及以上(API level >= 21)

支持 armeabi-v7a arm64-v8a x86 x86-64

1.3 OOMMonitor 接入

OOMMonitor 接入

2. Native Heap 泄漏监控
  koom-native-leak 模块用于 Native Heap 泄漏监控:它利用 Tracing garbage collection 机制分析整个 Native Heap,直接输出泄漏内存信息「大小、分配堆栈等』;极大的降低了业务同学分析、解决内存泄漏的成本。

思路总结:

hook malloc/free等内存分配器方法,用于记录Native内存分配元数据[大小、堆栈、地址等]–使用了爱奇艺的xhook库
周期性的使用mark-and-sweep分析整个进程Native Heap, 获取不可达的内存块信息[地址、大小]–使用到google的libmemunreachable库
利用不可达的内存块的地址、大小等从我们记录的元数据中获取其分配堆栈,产出泄漏数据[不可达内存地址、大小、分配堆栈等]
2.1 LeakMonitor 介绍
用于监控应用的 Native 内存泄漏问题,它的核心原理如下:

hook malloc/free 等内存分配器方法,用于记录 Native 内存分配元数据「大小、堆栈、地址等」
周期性的使用 mark-and-sweep 分析整个进程 Native Heap,获取不可达的内存块信息「地址、大小」
利用不可达的内存块的地址、大小等从我们记录的元数据中获取其分配堆栈,产出泄漏数据「不可达内存块地址、大小、分配堆栈等」

2.2 LeakMonitor 适用范围
Android N 及以上(API level >= 24)
仅支持 arm64-v8a

2.3 LeakMonitor 接入
LeakMonitor 接入

3. Thread 泄漏监控
  koom-thread-leak 模块用于 Thread 泄漏监控:它会 hook 线程的生命周期函数,周期性的上报泄漏线程信息。

3.1 ThreadLeakMonitor 介绍
用于监控应用的线程泄漏问题,它的核心原理:

hook pthread_create/pthread_exit 等线程方法,用于记录线程的生命周期和创建堆栈,名称等信息
当发现一个joinable的线程在没有detach或者join的情况下,执行了pthread_exit,则记录下泄露线程信息
当线程泄露时间到达配置设置的延迟期限的时候,上报线程泄露信息
3.2 ThreadLeakMonitor 适用范围
Android N 及以上(API level >= 24)
仅支持 arm64-v8a
3.3 ThreadLeakMonitor 接入
ThreadLeakMonitor 接入
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值