写点什么

快手开源自研 OOM 解决方案 KOOM

  • 2020-08-12
  • 本文字数:1700 字

    阅读完需:约 6 分钟

快手开源自研OOM解决方案KOOM

近日,快手宣布开源自研 OOM 解决方案KOOM。据了解,KOOM 是在客户端完成内存监控后,将解析报告上传到云端,传输文件大小仅为 KB 级,运行时用户无感知,对流量基本无影响,适合大规模普及应用,目前该方案已在快手全量业务中应用,OOM 率降低了 80%以上,效果显著。


OOM 是当前 Android 开发中的常见疑难问题,尤其是线上发生的 OOM 问题极难定位。业界当前最知名的方案 LeakCanary,通过监控 Activity/Fragment 泄漏优化 Java OOM 问题,多年来一直为广大 App 保驾护航,解决了 OOM 治理从 0 到 1 的问题。但面对行业不断复杂的业务环境和庞大用户流量,LeakCanary 仍有优化空间:受限于性能,无法在线上大规模部署,仅支持线下使用;只能定位 Activity&Fragment 泄漏,无法定位大对象、频繁分配等问题;需要人工一一分析,无法对问题聚类量化……为了彻底解决 OOM 问题,行业尝试了多种解决方案,通常是基于 LeakCanary 做优化,但至今没有能完全解决监控过程中的性能问题,普遍解决方法是通过采样的办法牺牲一小部分用户的体验来定位问题。


快手 OOM  Killer 沿用行业的研究思路,针对 LeakCanary 无法解决的难题进行自研改造,充分发挥 LeakCanary 原有优势的同时补足短板,打造了一套可以线上部署、兼顾线下、配置灵活、适用范围广泛、高度自动化,埋点、监控、解析、上报、分发、跟进、报警一站式服务的闭环监控系统,将绝大多数 OOM 问题拦截在灰度阶段,彻底解决了 OOM 问题。



KOOM 框架


快手 KOOM 核心流程包括:配置下发决策、监控内存状态、采集内存镜像、解析镜像文件(以下简称 hprof)生成报告并上传、问题聚合报警与分配跟进。

无主动触发 GC 不卡顿

之前行业的普遍做法是通过在 Activity.onDestroy()后连续触发两次 GC,并检查引用队列,判定 Activity 是否发生了泄漏,但频繁 GC 会造成用户可感知的卡顿,快手为实现无感触发设计了全新的监控模块,通过无性能损耗的内存阈值监控来触发镜像采集。将对象是否泄漏的判断延迟到了解析时,阈值监控只要在子线程定期获取关注的几个内存指标即可,性能损耗忽略不计。



内存监控流程图

高性能镜像 DUMP

采集内存镜像传统方案会造成应用完全冻结长达几秒,期间用户完全不能操作,严重损害用户体验。快手利用系统内核 COW(Copy-on-write,写时复制)机制,每次 dump 内存镜像前先暂停虚拟机,然后 fork 子进程来执行 dump 操作,父进程在 fork 成功后立刻恢复虚拟机运行,整个过程对于父进程来讲总耗时只有几毫秒,对用户完全没有影响。


暂停虚拟机需要调用虚拟机的 art::Dbg::SuspendVM 函数,谷歌从 Android 7.0 开始对调用系统库做了限制,快手自研了 kwai-linker 组件,通过 caller address 替换和 dl_iterate_phdr 解析绕过了这一限制。



Fork dump hprof 流程图

“不偷”用户流量的解决方案

传统方案得到的 hprof 文件通常比较大,占用用户大量磁盘空间,上传大文件浪费用户流量,且不利于问题聚类分析。快手采用了新的思路:采用边缘计算的思路,将内存镜像于闲时进行独立进程单线程本地分析,不过多占用系统运行时资源;分析完即删除,不占用磁盘空间;分析报告大小只有 KB 级别,不浪费用户流量。


分析报告生成流程总体分为三个环节,第一个环节扫描镜像构建索引,建立泄露查找分析的基础;第二个环节查找出泄露的对象,根据既有的 framework 知识以及人为设定的策略,执行对象泄露判定;第三个环节生成最终报告文件,将对象泄露路径、泄露数量、类统计、运行时信息添加至报告文件,辅助后续根据报告分析解决 OOM 问题。



解析镜像生成报告流程图


针对镜像回捞需求,对 hprof 进行运行时 hook 裁剪,只保留分析 OOM 必须的数据。裁剪还有数据脱敏的好处,只保留对分析问题有用的内存中类与对象的组织结构,并不上传真实的业务数据,充分保护用户隐私。

总结展望

快手 KOOM 计划做完整的客户端内存解决方案,开发者可以通过接入 KOOM,解决自己项目中的 OOM 问题。此次一期开源暂时只包括 Android Java OOM 解决方案,后续还将开源 Android 线程/文件描述符监控、Android Native OOM 监控、iOS OOM 监控等,最终实现帮助开发者解决各种场景下 OOM 的愿景。

项目地址:

https://github.com/KwaiAppTeam/KOOM


2020-08-12 15:265325

评论

发布
暂无评论
发现更多内容

数据规范的重要性

奔向架构师

数据治理 9月日更

源码解读Dubbo分层设计思想

vivo互联网技术

Apache dubbo 服务器 spi

小白也能看懂的dubbo3应用级服务发现详解

捉虫大师

dubbo 服务发现 Dubbo3

SaaS 102 | 做 SaaS 产品应该如何做决策?

Teddy Chan

创业 数据 SaaS 决策 电商SaaS

教你实现一个朴实的Canvas时钟效果

华为云开发者联盟

标签 函数 canvas 时钟

Python——lambda 函数

在即

9月日更

[资源收藏]高质量外文博客(持续更新)

baiyutang

9月日更

手撸二叉树之左子树之和

HelloWorld杰少

9月日更

一行Java代码实现游戏中交换装备

华为云开发者联盟

Java 线程 游戏 Exchanger JDK 1.5

翻转未来!钢铁之城重添色彩

脑极体

华为云首席产品官方国伟:没有人拥有看到未来的水晶球,云上突围之路如何走?

华为云开发者联盟

云计算 云原生 数字化转型 华为云 伙伴云

update 没有索引导致业务崩了,老板骂了一个小时

华为云开发者联盟

数据库 innodb 事务 索引 update 语句

5个非常重要的数据Oceanbase,TiDB,Cassandra,RocksDB,MemDB

hanaper

IOS技术分享| any自习室场景实现

anyRTC开发者

音视频 在线教育 移动开发 ios技术分享

移动端短语音消息音频格式选择

轻口味

android 音视频 9月日更

密码学系列之:海绵函数sponge function

程序那些事

密码学 程序那些事 海绵函数

【LeetCode】栈的最小值Java题解

Albert

算法 LeetCode 9月日更

数据库为何又如何走向分布式?

多颗糖

MySQL 数据库 分布式 raft TiDB

ECIC演讲精华|如何构建云原生应用下的高性能持久化存储?

焱融科技

技术 分布式 云原生 高性能 存储技术

FunTester抄代码之路

FunTester

Jmeter 测试框架 HttpClient FunTester ngrinder

潜入培训机构,顺出来一份价值 2.2W 的 Python 人工智能大纲

梦想橡皮擦

9月日更

大一 PingCAP、大二 JetBrains,专访 00 后开发者:千里冰封

郭旭东

开发者 采访 大学生

Python中如何优雅的使用assert断言

wangkx

Python assert

新思科技:部署数据安全战略,加强安全管理和隐私保护

InfoQ_434670063458

数据安全 新思科技

云随想二:云时代,你如何采购软件?

FLASH

云原生 采购软件

阿里云内部 WebRTC 研究分享| 内容合集

阿里云CloudImagine

阿里云 音视频 WebRTC 视频云 技术专题合集

macOS 制作 linux 启动盘

耳东@Erdong

Mac 软件 9月日更

【Flutter 专题】47 图解新的状态管理 Provider (二)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 9月日更

谈 C++17 里的 Visitor 模式

hedzr

c++ 设计模式 Design Patterns GoF设计模式

一个通用即时通讯(IM)系统的设计

OpenIM

Compose 中的图形

Changing Lin

9月日更

快手开源自研OOM解决方案KOOM_架构_快手技术_InfoQ精选文章