日活超过3亿的快手是怎么进行性能优化的?

2020 年 6 月 12 日

日活超过3亿的快手是怎么进行性能优化的?

在移动互联网时代,由于设备资源受限、网络不稳定等因素,Web 端和移动端的性能优化显得尤为重要,如果性能不好,用户就容易流失,ToC 的产品尤为明显,体验差的产品必然会被市场淘汰。如何做好性能优化是每个企业都会关注的。


在将于 11 月 24-25 日举办的 GMTC 全球大前端技术大会上,快手性能优化负责人杨凯将会分享《快手 APM 平台建设与性能优化》。他表示,“随着快手 App 功能越来越多,App 的性能也面临着严峻的挑战,诸如 App 越来越卡、内存占用越来越大、包大小不断增加等各类问题都严重影响着用户体验”。InfoQ 在会前采访了杨老师,我们一起来看看快手是如何应对性能挑战的。


InfoQ:快手 APM 指标监控平台的建设背景是什么?目前发展现状如何?


杨凯:APM 是我们针对快手的性能检测做的一个监控平台,其建立背景主要有两方面 , 一方面有很多用户反馈在使用我们的 App 时,遇到过卡、闪退和发热等问题;另一方面,我们从现有数据分析得出结论:性能对于用户活跃度有着重要影响。


目前,我们已经基本完成了崩溃、内存溢出(OOM)、应用无响应(ANR)、卡顿、启动、帧率(FPS)、包大小的线上、线下监控,电量、流量等监控正在开发中。线上的话,我们有天级、小时级的监控,并且重点指标有完善的报警机制。对于包大小、启动等,我们建立了一套实验室环境,可以监控到每个 mr(Merge request ) 导致的变化,以及日常迭代劣化。


APM 主要解决我们面临的各种稳定性和性能问题。效果非常明显:


  • 优化了 40% 的启动速度,提升了我们的 0 播、留存等关键产品数据。

  • 优化了 23M 包大小,大大降低了我们新用户获取成本。

  • 两个优化,都获得了快手技术线的绩效提升奖。



InfoQ:你们在搭建指标监控过程中遇到哪些难点?是怎么解决的呢?


杨凯:APM 可以做的事情很多,容易铺得很广,但每一点都做不透。另一方面,虽然大家都觉得性能重要,但如果没有数据的支撑,也容易陷入到处救火而看不到成绩得窘境。所以我们一方面参考业内经验、根据数据分析得出重要程度,评估每个方向的优先级,各个击破,抓住重点,力求每一点都做到极致,并且能从用户数据上得到充分的体现。


我们是一个音视频软件,所以对内存的使用,尤其是 C++ 申请的内存会比较多。内存泄露,OOM、地址空间不足等问题非常突出。业内现有方案对我们来说并不完全适用,需要我们根据自己的实际情况,开发监控、解决问题。业内有比较成熟的 malloc hook 方案监控 C++ 内存的申请、释放,但我们还需要知道哪些内存不可达,哪些大块内存被长时间持有,才能更好地解决我们的问题。


另外,我们在线上发现的性能问题,通常不是我们性能组能独立解决的,需要推动各业务方配合解决。这些工作会给大家日常的开发工作带来额外的负担,但它又对我们产品体验有很重要的影响。所以我们一方面尽量完善工具,上报更多更全的数据,另一方面我们要将大家作为一个整体团队,享受项目的成果。


InfoQ:内存优化过程中遇到的问题是如何解决的?


杨凯: 我们有一套自己的方法论,即定义问题、分析问题、解决问题、验收以及防劣化。


定义问题: 在最开始阶段,先将问题量化,例如用户卡,就需要定义什么叫卡,怎么监控用户卡?


  • 分析问题: 我们会在收集到足够的用户数据后,分析用户实际的问题场景、原因。

  • 解决问题: 很多问题,并不是性能组可以解决的,但是我们可以提供工具定位、发现问题,推动相关开发人员解决。

  • 验收: 对于一些重要的优化,我们会通过 AB 上线验收效果,回收技术数据和产品数据(例如优化 FPS,我们会看相关页面 CTR 的变化)。

  • 防劣化: 我们会制定一些机制、方案,防止已经优化的数据在日常的迭代中劣化,包括每个版本灰度期间的监控、线下实验室环境测试、开发阶段提醒等。


InfoQ:怎么进行内存优化?


杨凯: 内存主要是 Java 和 C 两部分,对于 Java,我们研发了一套线上裁剪、分析、上传用户本地镜像的方案,可以做到用户内存不足时,快速而准确地上报当时的 Java 内存状态,初步可以判断出来泄露和内存大户是谁。上报后我们会对所有用户的信息做汇总、展示。Java 部分的内存监控主要做了以下几点:


  • 内存镜像转储,我们研发了一种高效 dump 方案,解决了传统方法虚拟机内存转储需要暂停虚拟机的问题。

  • 内存镜像分析,研发了基于 shark 的低内存开销、低 CPU 开销的独立进程解析方案,采用了更为节省内存的高性能数据结构以及更为高效的内存索引,增加了同类型对象阈值用于 GC Root 最短路径搜索剪枝,可以在手机侧 10 分钟内完成 400M 镜像、200 万 对象的极端 case 解析。

  • 内存镜像裁剪,我们研发了一种 hook 虚拟机内存镜像转储时 IO 的高效裁剪方案,解决了传统裁剪效率低、成功率低的问题,辅以 zstd 压缩,90% 内存镜像可以压缩至 80M 内。



C 的内存 我们主要利用编译器插桩及 malloc hook 记录所有活着的内存块,利用 mark-and-sweep 算法在单独的进程中分析测试应用进程 Native Heap 中不可达的内存块。将发现的不可达内存上报后台。具体操作如下:


  • 利用编译器插桩及 malloc hook 记录所有活着的内存块(包含内存块地址、backtrace 信息),对性能影响较小。

  • 利用 mark-and-sweep 算法在单独的进程中分析测试应用进程 Native Heap 中不可达的内存块(包含内存块地址)。

  • 对于步骤 2 中收集到的不可达内存块,从 1 中获取其对应的 backtrace 信息,将泄漏信息上报至 APM 监控平台。

  • APM 监控平台解析泄漏信息(backtrace 信息符号化等),做友好的展示,业务方根据 APM 展示信息可快速定位泄漏问题。


InfoQ:如何优化卡顿?


杨凯: 我们定义的卡顿是:一个消息 / 任务在主线程执行超过 1s。


优化主要看卡顿的堆栈特征、当前 CPU 占用、其它线程正在执行的任务。通常有以下几种情况:CPU 占用过高(一般是主线程或者子线程任务重),主线程等锁(需要看其它线程当时的任务),系统服务忙(binder 调用耗时长)。解决方案一般需要结合场景、页面,增加 log 等,丰富更多上报信息,定位主要问题,或者缓解 CPU 占用。


InfoQ:在启动优化这部分做了哪些动作,优化前后对比效果如何?


杨凯: 启动优化我们主要是建立启动框架,将启动所有的任务,全部收敛到框架内,统计每个任务的耗时、相互依赖关系。


启动优化定位问题:


  • 将启动时运行的代码,按照功能,做成 task;

  • 线上收集每个 task 的耗时;

  • 在线下,在 Android 端利用 systrace、在 iOS 端利用自研的火焰图工具,来分析耗时。


优化手段:


  • 优化整体流程;

  • 分场景、分用户特性,推迟甚至取消一些 task (根据用户登录状态,用户使用习惯,后面我们会用机器学习预测 task 是否需要初始化);

  • 特别关注一些锁的等待、主线程 CPU 分配不足等问题;

  • 一些系统 API,背后会引发一系列的初始化(setcookie,会引起 WebView 内核初始化);

  • 主动 dex2oat;

  • 二进制重排、dex 重排。



另外,针对线上收集到的信息,重点优化耗时较多的任务。线下通过 systrace 等工具,定位、验证修复。然后依据用户的不同特征,初始化不同任务。例如,未登录用户不需要初始化拍摄相关任务。我们一期优化效果达到了 40%,后续几期优化,也收到了不错的效果。用户侧收益明显,用户(尤其是新用户)0 展示 、0 滑、 0 播放,以及留存等数据都有非常大的提升。


嘉宾介绍


杨凯,快手技术专家,客户端性能稳定性负责人。2017 年加入快手,先后负责快手海外版、性能稳定性。现在主要负责快手双端稳定性、性能优化,专注于提升快手可用性、易用性,提升用户使用的满意度,为公司高速发展保驾护航。团队成员均来自于一线互联网公司、主流手机厂商,对 Android 核心技术有着深入的理解和丰富的经验。


关注GMTC全球大前端技术大会,迅速 get 百度、快手、高德的最新性能优化的技术实践。


2020 年 6 月 12 日 10:5614066

评论

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

GoF 23种设计模式之单例模式

无心水

架构师 单例模式 极客大学架构师训练营 GoF 23种设计模式

设计模式

ashuai1106

设计模式 架构师 极客大学架构师训练营 23种设计模式

架构师训练营week03 总结

傅晶

架构师 极客大学架构师训练营

第三周总结

大雄

架构师训练营第三章总结

吴吴

第3周学习总结

Glowry

极客大学架构师训练营

架构师训练营第 0 期第三周作业

无名氏

单例模式 组合模式

Java反射与内省(参考小米内部资料)

知春秋

Java 反射 内省

第三周作业一

潜默闻雨

架构师训练营-W03S-代码重构

BlazeLuLu

极客大学架构师训练营

架构师训练营第三周作业

Java 极客大学架构师训练营

第三周作业

大雄

架构师训练 - 第三周作业

X﹏X

第三周-作业

铁血杰克

架构师训练营 -week3- 学习总结

晓-Michelle

极客大学架构师训练营

第03周 重构软件代码 命题作业

Jaye

Week3 - 总结

Coder

极客大学架构师训练营

游戏夜读 | 玩游戏能得到什么?

game1night

架构师训练营第三周作业

Bruce Xiong

第03周 重构软件代码 学习总结

Jaye

架构师训练营第三章作业

吴吴

第三周-总结

铁血杰克

week3-作业一

Coder

架构师训练营第 0 期第三周学习总结

无名氏

第二周

Geek_zhangjian

本周学习总结

Geek_zhangjian

2020-06-20-第三周作业

路易斯李李李

【架构训练 Week03 作业】Review

Rex

「架构师训练营」单例与组合模式的应用

Amy

极客大学架构师训练营 作业 第三周

【架构训练 Week03 作业】

Rex

架构师训练营 Week 03 作业

Wancho

日活超过3亿的快手是怎么进行性能优化的?-InfoQ