开发态快速定位DMA(ION)泄漏

0 评论 136 浏览 0 收藏 11 分钟

 在HarmonyOS上,DMA内存是指有DMA驱动分配的,支持在多进程、多硬件之间共享访问的RAM内存(特别说明,DMA内存与ION内存是相同的概念)。在HarmonyOS系统中,应用一般通过系统开放的ArkUI、图形和媒体的相关接口间接使用DMA内存,例如ArkUI中的XComponent, Image和Web组件,图形的ImageNative和NativeBuffer,AvCodec的编解码,图片的PixelMap接口等。当应用占用的DMA内存超过阈值时,即认为应用发生DMA内存泄漏。

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

开发态快速定位DMA(ION)泄漏-华为开发者话题 | 华为开发者联盟

1.1 DMA泄漏分析流程与高频泄漏场景

在HarmonyOS上,DMA内存是指有DMA驱动分配的,支持在多进程、多硬件之间共享访问的RAM内存(特别说明,DMA内存与ION内存是相同的概念)。在HarmonyOS系统中,应用一般通过系统开放的ArkUI、图形和媒体的相关接口间接使用DMA内存,例如ArkUI中的XComponent, Image和Web组件,图形的ImageNative和NativeBuffer,AvCodec的编解码,图片的PixelMap接口等。当应用占用的DMA内存超过阈值时,即认为应用发生DMA内存泄漏。

1.1.1 高频泄漏场景

1.1.1.1 Image控件泄漏或缓存过多导致内存泄漏

应用程序中的 Image 控件未正确释放DMA内存,引发DMA内存泄漏,最终引发系统图像服务异常或应用崩溃。

1.1.1.2 ArkWeb控件泄漏导致内存泄漏

应用程序中的 ArkWeb控件未正确管理ArkWeb控件的生命周期或缓存策略,引发DMA内存泄漏,最终引发系统异常或应用崩溃。

1.1.1.3 使用SurfaceNDK接口分配内存未释放导致内存泄漏

应用程序中的Surface的NDK接口分配的DMA内存未释放,引发DMA内存泄漏,最终引发系统异常或应用崩溃。

1.1.1.XComponent组件泄漏或者缓存过多导致内存泄漏

应用程序中的XComponent组件未正确释放DMA内存,或组件缓存无限增长,引发DMA内存泄漏,最终引发系统异常或应用崩溃。

1.1.1.5 视频软硬编解码器API接口使用不当导致内存泄漏

应用程序中的视频软硬编解码器API接口使用不当导致视频解码/编码时分配的DMA内存未释放,引发DMA内存泄漏,最终引发系统异常或应用崩溃。

1.1.2 标准化排查流程

       1. 复现与日志获取:使用DevEco ProfilerAllocation模板开启统计模式录制泄漏场景,重复多次操作疑似泄漏场景复现问题。

       2. 识别泄漏点 点击All Anonymous VM中的VM:ION子泳道,在下方详情Call Tree标签页中选择Created & Existing,查看内存占比较高的调用

       3. 分析调用:优先在调用信息中寻找占比较高且与业务代码强相关的Symbol Name,即Category中为亮色。根据调用分析相关代码(双击跳转源码),排查内存未释放原因。

       4. 代码审查:结合调用,梳理相关代码中的内存持有逻辑,定位泄漏根因。

           • 业务逻辑未发现异常:查看DMA内存信息,结合DMA内存信息分析。

           • 业务逻辑存在异常:修改相关代码。

       5. 修复与验证:修改代码后,重复步骤 1,确认内存曲线回归平稳。

图1

1.2 DMA内存泄漏分析案例

1.2.1 案例背景

现象:本案例中,通过反复操作复现问题场景,观察到应用Graph内存占用呈现”阶梯式持续增长”趋势。

初步判断:使用 Allocation 统计模式录制内存上涨过程,观察 Memory 泳道中的 Graph 曲线,呈现出典型的“阶梯式增长”,确认存在DMA内存泄漏。

       • Graph 子泳道:应用使用的DMA内存

图2

图3

 

1.2.2 分析流程

1.2.2.1 步骤1:通过Allocation录制泄漏场景

       1. 基于DevEco Studio Profiler插件的Allocation模板分析堆内存分配、释放的信息,调用信息。这些信息中包括已释放内存和未释放内存。启动应用进程,选择Profiler工具  选择设备与应用进程  选择Allocation模板  创建Session  配置录制选项。

图4

       2. 开启统计模式,可以打开JS记录和异步记录开关。由于DMA内存的分配频率相比于NaitveHeapMalloc更低,因此可关闭Malloc采集,减少对DMA内存分析的影响。

图5

       3. 点击按钮启动录制并复现问题场景。

图6

1.2.2.2 步骤2:查看DMA内存调用栈

1. 框选All Anonymous VM中的VM:ION子泳道。

       • VM:ION子泳道:用于显示DMA内存分配数据。

       2. 在下方详情区的“Statistics”页签中选择Created & Existing。

       • All Allocations框选的时间段的所有分配内存信息。

       • Created & Existing:默认选中,在框选范围的起点之后分配的,且在框选范围的终点之前没有释放的内存数据。

       • Created & Released:在框选范围的起点之后分配的,且在框选范围的终点之前已经释放的内存数据。

图7

3. 切换到“Call Trees”页签,该部分数据展示了详细的内存分配栈信息。

图8

1.2.2.3 步骤3:分析DMA内存调用栈

优先在内存分配栈信息中寻找占比较高且与业务代码强相关的Symbol Name,即Category中为亮色。根据调用栈分析相关代码(双击跳转源码),排查内存未释放原因。

图9

 

1.2.3 修复验证

       • 修改代码增加 image.PixelMaprelease 方法释放内存。

       • 重新运行应用,再次使用 Allocation 录制内存分配

       • 重复多次操作泄漏场景。

       • 验证结果

          ▪ 每次页面退出后,内存曲线回落至基线。

          ▪ 泄漏问题已修复。

图10

 

1.3 附录

1.3.1 查看进程中DMA内存信息

1. 查找进程pid

启动应用进程,选择Profiler工具 → 选择设备与应用进程,即可看到进程pid。

图11

2. 获取到pid后,在终端中执行hdc shell,然后执行命令hidumper –mem pid –show-dmabuf 对比复现前和复现后的数据。根据buf_nameleak_type排查相关组件。

图12

 

获取指定pid的DMA内存详细信息,开发者可以根据DMA内存信息中的buf_name、leak_type等列定界可疑泄漏组件,参考故障日志分析方法 

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

题图来自Unsplash,基于CC0协议

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

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