KOOM(Kwai OOM, Kill OOM)是快手性能优化团队在处理移动端OOM问题的过程中沉淀出的一套完整解决方案。其中Android Java内存部分在LeakCanary的基础上进行了大量优化,解决了线上内存监控的性能问题,在不影响用户体验的前提下线上采集内存镜像并解析。

一、KOOM 背景

随着移动端业务逻辑日益复杂,4K编解码、AR魔表等高内存需求场景的逐渐普及,OOM问题已成为快手客户端稳定性治理的头号顽疾。 在日常版本迭代过程中,间或会发生OOM激增,而线上环境非常复杂,仅AB实验就有上千种,事前预防以及事后还原都无法做到,因此急需高性能的线上内存监控方案。一期开源的Android Java内存监控方案,我们调研了LeakCanary以及美团和UC等发表的相关技术文章,发现业内的优化方向主要集中在内存镜像的解析部分,而内存镜像dump部分,一直没有方案能解决dump过程中app长时间冻结的问题。经过深入研究,我们发现可以利用Copy-on-write机制fork子进程dump,满足我们的需求。

二、KOOM 指南

1. 运行demo

首先建议跑通一下项目自带demo(koom-demo项目),对KOOM提供的基础功能和概念有一个大致的了解。

2. 依赖接入

dependencies {
    implementation 'com.kwai.koom:java-oom:1.0.4'
}

3. 初始化

Application初始化:

public class KOOMApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        KOOM.init(this);
    }
}

4. Java-oom 报告获取

当内存使用异常,触发内存镜像采集并分析后,会生成一份json格式的报告。

可以择机主动获取:

public void getReportManually() {
    File reportDir = new File(KOOM.getInstance().getReportDir());
    for (File report : reportDir.listFiles()) {
        // Upload the report or do something else.
    }
}

也可以实时监听报告生成状态:

public void listenReportGenerateStatus() {
    KOOM.getInstance().setHeapReportUploader(file -> {
        // Upload the report or do something else.
        // File is deleted automatically when callback is done by default.
    });
}

5. Java-oom 组件介绍

内存监控组件 定时采集内存资源占用情况,超过阈值触发内存镜像采集,决定镜像dump与分析时机,关键代码参考Monitor.java

内存镜像采集组件 高性能内存镜像采集组件,包含fork dump和strip dump两个部分,关键代码参考HeapDumper.java

内存镜像解析组件 高性能内存镜像解析组件,基于shark解析器定制优化,泄露判定关键代码参考LeakDetector.java