RSS 内存泄漏排障全攻略(下篇)

0 评论 1265 浏览 0 收藏 17 分钟

本原创文章帖发布在华为开发者联盟社区,欢迎开发者前往访问评论交流,更多与该内容相关讨论,请点击原帖查看:

RSS 内存泄漏排障全攻略(下篇)

运维态与开发态分析方法,从日志到代码行的”破案之路”

前言

在《RSS 内存泄漏排障全攻略(上篇)》中,我们已经搞懂了 RSS 内存泄漏的基本概念,学会了如何查看 RSS 内存、订阅故障事件,并掌握了 smaps、NMD、内存栈三类维测日志的规格与获取方法。这些内容为我们搭建了完整的”认知框架”和”工具箱”。

本篇将在此基础上,聚焦”如何用这些工具真正定位到泄漏根因”。我们将从运维态的 smaps 日志分析和内存栈日志分析方法讲起,借助二级根因速查表快速定界故障类型;再转到开发态,介绍如何使用 DevEco Studio、hidumper、hiprofiler 等工具在本地复现并定位问题;最后给出把 RSS 内存泄漏扼杀在摇篮里的实践建议。

建议结合上篇一起阅读,让”认知—感知—分析—定位”形成完整闭环。

六、运维态问题分析:从日志到根因的“破案之路“

6.1 smaps 日志分析方法

smaps 日志就像一份”内存账单”,通过分析它,我们可以按照内存类别聚类并排序,找出占用最高的内存类型——这就是本次内存泄漏的二级根因。

具体步骤如下:

          • 通过订阅资源泄漏事件,在沙箱中接收故障日志

/data/storage/el2/log/resourcelimit/RESOURCE_OVERLIMIT_XXXX_XXXX.log

          • 在故障日志中搜索关键字 LOGGER_MEMCHECK_SAMPLIFY_SMAPS_INFO,读取数据

// log
// LOGGER_MEMCHECK_SAMPLIFY_SMAPS_INFO 日志示例
// Size:内存段大小 Rss:常驻内存 Swap:交换内存
// Category:内存类别 Counts:数量 Name:内存段名称
Size Rss Swap Category Counts Name
512 44 8 arkts-static heap 2 [anon:ArkTs Static Object Space]
256 180 44 arkts-static heap 1 [anon:ArkTs Static Non Movable Space]
1582104 112 0 AnonPage other 42 [anon]
1780224 1044 292 ark ts heap 34 [anon:ArkTS Heap]
512 12 4 ark ts heap 2 [anon:ArkTS Heapread only space]
3072 1424 1112 ark ts heap 12 [anon:ArkTS Heapnon movable space]
256 40 8 ark ts heap 1 [anon:ArkTS Heapshared non movable space]
256 44 4 ark ts heap 1 [anon:ArkTS Heapshared read only space]
40960 320 40160 ark ts heap 1 [anon:ArkTS Heapshared huge object space]
5888 5712 16 ark ts heap 23 [anon:ArkTS Heapappspawn space]
512 272 32 ark ts heap 2 [anon:ArkTS Heapshared old space]
768 36 340 ark ts heap 3 [anon:ArkTS Heapsemi space]
2560 1592 0 ark ts heap 10 [anon:ArkTS Heapshared appspawn space]
33554432 120 0 AnonPage other 5 [anon:partition_alloc]
128 32 4 FilePage other 4 /system/bin/appspawn
32 0 32 native heap 1 [anon:native_heap:meta]
2124 1796 8 .so 4 /system/lib/ld-musl-aarch64.so.1
2992 48 16 AnonPage other 1 [anon:ld-musl-aarch64.so.1.bss]
4 4 0 AnonPage other 1 [kshare]
16 16 0 AnonPage other 2 [shmm]
6288 3724 2520 native heap 108 [anon:native_heap:brk]
280 4 0 FilePage other 1 system/etc/zoneinfo/tzdata
47136 904 872 native heap 24 [anon:native_heap:jemalloc meta]
9186304 6041112 277404 native heap 9 [anon:native_heap:jemalloc]
......

分析技巧:按照 Category 列进行聚类,对每种类型的 Rss 列和 Swap 列求和,排序后找出内存总量占用最大的类型。

例如,经过排序发现 native heap 类型的内存总量最大:

// log
// native heap 类型内存总量最大
Size Rss Swap Category Counts Name
47136 904 872 native heap 24 [anon:native_heap:jemalloc meta]
9186304 6041112 277404 native heap 9 [anon:native_heap:jemalloc]
......
// 结论:此时发生的 RSS 内存泄漏的二级故障为NativeHeap堆过大

一旦确定了二级根因,就可以将内存栈日志导入 DevEco Studio,进一步定位到具体的泄漏代码行。

图 1:DevEco Studio 中 smaps 日志分析界面

6.2 内存栈日志分析方法

       将内存栈日志导入 DevEco Studio 后,按以下步骤排查可疑内存泄漏点:

          • 单击“导入文件“按钮导入内存栈日志

          • 基于前置分析的二级根因选择不同的泳道:

          • 如果二级故障为 NativeHeap 堆过大,选中 All Heap 泳道

          • 如果二级故障为其他类型,选中 ALL Anonymous VM 泳道

          • 单击 Call Trees 查看内存申请调用栈

          • 选择 Created & Existing,筛选申请并且未释放的内存及其调用栈

          • 找到内存申请异常的内存及其调用栈

          • 结合调用栈对代码进行分析,找到泄漏根因

图 2:DevEco Studio 中内存栈日志分析界面

七、二级根因速查表:Category 对应什么故障?

通过分析 smaps 日志中的 Category 列,可以快速定位到二级故障根因。以下表格列出了常见的内存类别及其对应的故障类型和定位手段:

内存类别(Category) 二级故障根因 定位手段
native heap NativeHeap 堆过大 参考 NativeHeap 堆过大导致内存泄漏故障模式说明
ark ts heap 匿名映射-动态 ArkTS 虚拟机堆内存较大 参考 ArkTS 内存泄漏故障模式概述
AnonPage other 其他匿名页映射大 参考匿名映射过大导致内存泄漏故障模式说明
FilePage other(ashmem) 匿名映射-Ashmem 过大 优先用 smaps 定界到二级根因
jsvm heap 匿名映射-龙雀 JSVM 虚拟机堆内存较大 优先用 smaps 定界到二级根因
kotlin heap 匿名映射-KMP Kotlin 堆内存较大 优先用 smaps 定界到二级根因
dart heap 匿名映射-Flutter 虚拟机堆内存较大 优先用 smaps 定界到二级根因
rn-hermes heap 匿名映射-RN 虚拟机堆内存较大 优先用 smaps 定界到二级根因
arkweb-js heap 匿名映射-ArkWeb V8 虚拟机堆内存较大 优先用 smaps 定界到二级根因
arkts-static heap 匿名映射-静态 ArkTS 虚拟机堆内存较大 优先用 smaps 定界到二级根因
stack 栈内存过大 优先用 smaps 定界到二级根因
.so 文件映射-共享库过大 优先用 smaps 定界到二级根因
.ttf 文件映射-字体文件过大 优先用 smaps 定界到二级根因
.hap 文件映射-HAP 包过大 优先用 smaps 定界到二级根因
FilePage other 文件映射-其他过大 优先用 smaps 定界到二级根因
/ NativeHeap、ArkTS 虚拟机堆、文件映射等组合使用过大 优先用 smaps 定界到二级根因

(表 1:RSS 内存泄漏二级根因对照表)

八、开发态问题分析:在本地“重现案发现场“

对于在开发验证过程中遇到的 RSS 内存泄漏问题,或者运维态遇到的已知场景的泄漏问题,开发者可以在本地使用 DevEco Studio 的 Profiler 工具、hidumper 等开发工具对问题进行复现并抓取维测分析。

8.1 故障分析工具说明

hidumper:命令行维测利器

使用 hidumper –mem pid 获取指定进程的内存使用情况:

// bash
# hidumper --mem 9598
// 获取进程 9598 的内存使用情况
-----------------------------------------------[memory]----------------------------------------------
Pss Shared Shared Private Private Swap SwapPss Heap Heap Heap
Total Clean Dirty Clean Dirty Total Total Size Alloc Free
( kB ) ( kB ) ( kB ) ( kB ) ( kB ) ( kB ) ( kB ) ( kB ) ( kB ) ( kB )
-----------------------------------------------------------------------------------------------------
GL 0 0 0 0 0 0 0 0 0 0
Graph 0 0 0 0 0 0 0 0 0 0
ark ts heap 46325 6888 0 45804 0 88 2 0 0 0
arkts-static heap 4 0 0 4 0 416 15 0 0 0
guard 0 0 0 0 0 0 0 0 0 0
native heap 2382093 3528 0 2381572 0 31500 1365 68892 67285 3247
.hap 41744 0 0 41744 0 0 0 0 0 0
AnonPage other 1544 356 0 1500 0 6140 172 0 0 0
stack 420 0 0 420 0 0 0 0 0 0
.db 32 0 0 32 0 0 0 0 0 0
.so 9701 56360 3720 1020 1096 31772 905 0 0 0
dev 17 0 384 16 0 0 0 0 0 0
.ttf 436 1564 0 12 0 0 0 0 0 0
arkweb-pa heap 0 0 0 0 0 120 4 0 0 0
FilePage other 314 2332 8 0 12 4284 169 0 0 0
-----------------------------------------------------------------------------------------------------

使用 hidumper –mem-smaps pid 获取指定进程的详细内存使用情况(会累加相同内存段的内存值):

// bash

# hidumper --mem-smaps 9598
// 获取进程 9598 的详细 smaps 内存信息
--------------------------------[memory]---------------------------------
Shared Shared Private Private
Size Rss Pss Clean Dirty Clean Dirty Swap SwapPss Counts

hiprofiler:堆内存分配调用栈抓栈工具

当定界到 native heap、AnonPage other、FilePage other、Ashmem 等类型内存发生泄漏时,可以使用 hiprofiler 对进程的堆内存分配操作抓栈,分析泄漏点。

DevEco Profiler 调优工具

通过 DevEco Studio 中 Profiler 工具的 Allocation 功能,可以对应用进程的内存申请趋势以及内存申请调用栈进行分析,定位出具体泄漏点。

8.2 故障分析方法

       在 DevEco Studio 中调试时遇到应用闪退,可以按以下步骤排查:

          • 在 DevEco Studio 中找到日志组件,选择“应用终止“,筛选调试应用的历史退出原因

          • 如果原因为 RssThresholdKiller,说明应用发生了 RSS 内存泄漏故障

图 3:DevEco Studio 日志组件中查看应用终止原因

          • 确认问题为 RSS 内存泄漏后,使用 Profiler 工具的 Allocation 功能进行分析

          • 如果发现应用内存占用超出预期,可以初步断定存在内存泄漏问题

图 4:DevEco Studio Allocation 分析界面

          • 展开 Memory 泳道,观察 Native Heap、AnonPage Other、Dev、Guard、.so、.ttf、Stack 等泳道的增长情况,初步定界为 RSS 内存泄漏问题,并精确到二级根因

图 5:DevEco Studio Memory 泳道分析界面

       • 最后根据二级根因,结合内存栈日志分析方法定位内存泄漏点

九、结论与建议:把RSS内存泄漏扼杀在摇篮里

RSS内存泄漏不是玄学,而是一门可以通过系统方法排查的技术活。总结一下本文的核心要点:

       1. 建立内存监控意识:不要等系统来“请”你的应用。通过订阅资源泄漏事件和应用终止事件,提前感知内存异常,做到早发现、早处理

       2. 掌握日志分析能力:smaps日志帮你找到内存泄漏的“大类”,NMD日志帮你定位到具体内存块,内存栈日志帮你追溯到代码行。三者配合,形成完整的排查闭环。

       3. 善用开发工具:DevEco Studio的Profiler Allocation功能、hidumper命令行工具、hiprofiler抓栈工具,是排查内存泄漏的三大利器。开发态多花10分钟排查,运维态就能少花10小时救火。

       4. 关注低端设备:低端设备内存总量小,更容易触发低内存状态。如果你的应用面向低端设备,内存优化不是“锦上添花”,而是“生死攸关”。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

最好的内存优化,是在写第一行代码时就考虑到内存管理。但即使代码已经写完了,掌握正确的排查方法,也能让问题迎刃而解。

🔗 官网开发者学堂视频:https://developer.huawei.com/consumer/cn/training/result?type2List=201783644516849879&orderBy=1&courseType=5

     🔗 社区DFX专题文章:  https://developer.huawei.com/consumer/cn/forum/subject/2101218731402391001

【扫码加入 HarmonyOS DFX 技术交流群】

本文由 @华为开发者联盟 授权发布于人人都是产品经理。未经作者许可,禁止转载

题图来自Unsplash,基于CC0协议

该文观点仅代表作者本人,人人都是产品经理平台仅提供信息存储空间服务

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
海报
评论
评论请登录
  1. 目前还没评论,等你发挥!