HarmonyOS开发探索:使用Snapshot Insight分析ArkTS内存问题

  1.  识别内存问题

    当怀疑应用存在内存问题的时候,首先使用DevEco Profiler的Allocation Insight来度量内存在问题场景下的大小变化以及整体趋势,初步定界问题出现的位置(Native Heap/ArkTS Heap/dev等)。

    在初步识别内存问题出现的位置时,录制时需要将Allocation Insight中的后两条泳道取消勾选,只录制Memory这一条泳道。

    (注:因为另外两条泳道会开启对内存分配、内存对象的抓取,这些功能会带来额外的开销,可能会对我们初步定界问题产生噪音,阻碍分析,故先排除)

    cke_1205.png

    录制过程中,尽可能多的触发会导致内存问题的操作,将问题放大,便于快速定界问题点。复现完成后,结束录制,选中Memory泳道(直接选中泳道详情区域会展示完整的泳道数据),查看详情区域的数据 (注:详情区域数据采用PSS的维度衡量,数据近似于使用`hidumper --mem $pid`的第一列PSS值)

    cke_6725.png

    通过详情区域的详细内存占用数值,我们能够大致定界出有哪些位置的内存可能存在问题。

    因为本文主要介绍如何定位ArkTS的内存问题,故只关心ArkTS Heap相关的部分。从表格的数据中发现,ArkTS Heap有不少的上涨,这说明在方舟虚拟机内的堆内存上可能存在内存泄漏问题,需要进一步分析。

    cke_8190.png

  2. 分析ArkTS Heap

    ArkTS在编译后会生成JS代码,运行在方舟虚拟机中。分析虚拟机的堆内存问题时会用到内存快照(Heap Snapshot/Heap Dump)技术,DevEco Profiler提供了分析内存快照的Snapshot Insight。

    cke_10246.png

    点击领取→纯血鸿蒙Next全套最新学习资料(安全链接,放心点击希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,

    在使用Snapshot分析时,通常会使用三快照技术(Three Snapshot Technique),通过内存快照的对比视图将某两次快照之间分配且仍然驻留的内存筛选出来,这些对象中的一部分就可能是导致内存泄漏的对象。通用的流程为:

    打开应用,初始化场景 (触发GC)-> 拍摄第一次Snapshot作为基准 -> 多(N)次触发内存泄漏操作 -> 拍摄第二次堆快照 -> 触发主动GC -> 拍摄第三次堆快照。由于方舟虚拟机提供了在获取堆快照之前自动GC的功能,因此我们可以将上述流程简化为两步,同时加上Profiler的录制功能,整体流程为:

    打开应用,初始化场景 -> 开启录制Snapshot Insight-> 拍摄第一次Snapshot作为基准 -> 多(N)次触发内存泄漏操作 -> 拍摄第二次堆快照 -> 结束录制。

    录制完成后,会得到如下图所示的数据:

    cke_11741.png

    录制过程中,我们采集了两次堆快照,对应在Profiler的界面上就是两个紫色的条块,每一个条块内的数据都是当前的虚拟机堆快照。条块上的数字大小代表的是虚拟机堆内存的实际占用

    由于在每次拍摄堆快照之前,虚拟机都会触发GC,所以理论上堆快照内存在的对象都是当前虚拟机已经无法GC掉的对象,所以我们可以将两个堆快照进行比较,来查看哪些对象是我们在触发问题场景时新增了且不能释放的。

    点击Snapshot Insight面板的Comparison页签,将两次Snapshot进行比较,如下图。图中数据的含义为以Snapshot1作为基准,Snapshot2对比Snapshot1的数据变化量。

    cke_13426.png

    在触发内存问题场景时将问题触发N次,在比较视图中首先就去找与N强相关、与业务代码强相关的constructor,首先来分析这些对象是否正常。

    首先介绍一下Snapshot比较视图中各项数据的含义,如下图:

    cke_15760.png

    在找到相关的业务关联的对象后,可以从右侧More区域的Retainers里面一层层去寻找、排查在引用链上的可疑对象(一般指与业务代码关联的对象,例如上图中的setData)。

    当发现了引用链上的业务对象时,就可以通过对象索引功能(IDE正在实现)可以一环一环找到各个对象的引用关系,通过排查在引用链上的对象传递关系,在代码中分析相关的逻辑来找到内存泄漏的位置。

  3. 应用代码排查

    具备了通用的分析能力,就需要根据业务场景来排查代码,分析代码中出现问题的位置。

    第一步,就是先缩小问题场景,让场景尽可能的单一,最好是单一操作单一组件出现问题。涉及的代码越少,定位效率越高

    第二步,开始排查代码,首先需要排查的模块就是在上面提到的Snapshot分析中所找出到的问题场景中两个Snapshot对比里增加的与业务代码相关的对象以及其引用链(这里在排查引用链时,可以参考:ArkTS内存泄露分析,在引用链中有一些对象是虚拟机内部的,基本不需要开发者关心)。

    这一步在代码场景比较单一的时候,可以结合引用逻辑与代码来一起分析是什么原因造成的,例如闭包被全局对象持有无法释放。结合目前的经验来看,从引用链上虽然无法直接定位到代码具体位置和原因,但是可以分析到一些代码关联性的。

    但是在引用链上也很可能会挂载一些ArkUI相关的对象,如果定位到大量的应用对象最终的引用关系都是引用到了ArkUI对象上,可能需要找到相关的框架同事来协助定位。

    这一步中可能有两个问题:

    1. 对象实例以及引用链上有很多对象都和业务代码相关联,应该从哪一个下手。

    2. 对象引用链实在太过复杂,具体要看哪里,怎么一步步往下看。

    针对这两个问题:

    1. 关联对象多,这时候不要发散,力出一孔,优先解决一个问题,顺带着可能就解决掉了一串问题,然后再根据可能涉及到的多个模块逐个攻破

    2. 参考上面的Ark调优工具指南,使用“深度优先遍历”的方法先分析一条引用链,找到其中的可疑点,再慢慢地发散到其他的引用链上,找出一些共性的对象,最终汇总起来再集中审视所有的可疑对象

    第三步,通过在上面步骤中分析的代码,最好相关模块的开发人员来走读一遍代码,通过白盒来分析可能存在的问题点。如果实在模块逻辑太过复杂,那就只有请出注释大法,二分的来定位问题位置。

  4. 实践

    这里使用一个某视频应用内存泄漏的问题来简单介绍具体的问题定位方法。

    问题出在视频应用的搜索页上,在点击进入搜索页搜索内容后退出搜索页,发现内存增长不会回退,且不断操作进入/退出时内存数据会一直增加,因此怀疑这步操作存在内存泄漏。

    采用章节2中提到的两步Snapshot法:

    1. 打开应用,在初始化的页面上拍摄一次ArkTS堆内存快照。

    2. 反复进入搜索页搜索内容,一共触发6次,并在搜索完之后推出搜索页回到主页(步骤1)的状态。

    3. 拍摄第二次ArkTS堆内存快照,拍摄完成后停止录制等待解析完毕。

    快照解析完成后,即可使用对比视图查看在两次相同状态下的应用内存区别,下面是对比视图:

    cke_17628.png

    结合业务逻辑,从对比视图中发现,MainSearch这个搜索逻辑所对应的业务对象在两次Snapshot之间增加了4个,并且是虚拟机无法GC回收掉的对象(因为虚拟机在做dump之前自动触发一次Full GC),而从B站的业务逻辑中确认,该对象在退出搜索页面时就应该被销毁,因此基本可以确定该对象产生了泄漏。

    接下来就要分析为什么会这个对象不会被GC回收掉,在方舟虚拟机中,对象不会被GC回收的根本原因是从GC Root到该对象有至少一条引用链,导致该对象间接甚至直接被GC Root引用,虚拟机在做可达性分析时,发现该对象被GC Root引用,因此不会回收该对象。接下来就需要借助工具中的引用链来分析为什么对象会被GC Root引用,找出其中的引用关系并解决掉错误的引用关系,以释放相应的内存。虚拟机GC详细介绍可参考:解密方舟的高性能内存回收技术——HPP GC。

    cke_19520.png

    打开该构造器所对应的树状结构,其子节点均为该构造器对应的实例对象,也即在这次快照中仍然存活的对象,再将该对象节点展开,其下方节点为对象的属性(Fields)以及引用链(Retainers),点击该对象即可在Reatiners中分析其引用链。

    cke_21371.png

    引用链中有个重要信息是Distance,即该节点距离GC Root的距离(所需要经过的节点个数),我们在分析引用链上的对象问题时,通常会逐步找Distance越来越小的对象,以对该对象到GC Root上对象的进行分析,如上图所示,就是一条从泄漏对象(Main Search)到GC Root的引用链。下面挑选其中一小部分来介绍如何分析引用链。

    cke_23440.png

    图中是一个顺序展开的树形引用链结构,其中每一行标注了字母,后面用字母代替该行的数据。

    引用链在树形结构的展示中是一个反向的逻辑,即下面一行的属性引用了上面一行的对象,拿A和B举例,上图中的关系就代表着A中RelationCenter这个对象的_instance属性引用了B中的RelationCenter JSObject,而B中RelationCenter这个对象的subscribers属性又引用了JSArray对象,再往上分析以此类推。

    反过来也可以这么理解:B中RelationCenter JSObject就是A中RelationCenter对象的_instance属性。

    用伪代码可以描述为:

    A:RelationCenter._instance = B:RelateionCenter JSObject
    
    B:RelateionCenter JSObject.subscribers = C:JSArray
    
    C:JSArray[7] = D:RelationButton.anonymous(line:84)

    通过这个引用关系,可以大体上确定出代码的变量引用逻辑,接下来就要去白盒分析代码的问题所在,即这些引用是否合理,若不合理,需要解决这些引用关系

    在此视频应用的这个问题中,分析发现这里在 GC Root距离为 7 的节点上(上图中D), 看到 RelationButton anonymous(line:84)以及RelationCenter相关信息(如果需要查看该对象的详细信息,可以点击这一行字符后面的蓝色按钮,跳转到对象详情面板),

    我们打开项目在编译后的文件中(build目录下的ts文件)找到 RelationButton的84行,分析逻辑发现是一个 subscriber,首先考虑是否是因为忘记解绑这个定位导致问题,然后去自己的 ets 代码找问题。

    最终定位到相关的源码文件发现是因为没有解除相关代码的订阅导致内存泄漏,添加解绑逻辑后再次抓取快照测试,该引用链消失,这个问题点解除,接下来以相同的方式分析其余类似问题。

    上面的例子只是简单介绍如何通过引用链来分析可疑的内存泄漏对象的方法,并未过多描述其中的分析排查思路和逻辑,总的来说,在应用侧排查内存问题时,主要有以下几个关注点:

    1. Snapshot的对比视图中,优先观察与当前问题场景强相关的业务对象,虚拟机内部对象以及一些基础对象(例如ArkInternelXXX/(array)/GLOBAL等等)可以先不关心,可以使用过滤功能过滤出业务代码相关的对象(例如使用com.huawei进行过滤)。

    2. 在分析引用链的过程中,引用链上可能掺杂了一些虚拟机内部的对象(因为虚拟机需要使用一些内部对象或类型来管理/表达业务对象),所以引用链的分析过程中也可以优先关注业务侧的对象,先忽略掉其中的虚拟机内部对象(虚拟机内部对象的描述,可以参考:ArkTS内存泄露分析)。

    3. Snapshot中展示的对象可能非常多,这可能是由于某一条引用链上引用了很多的对象所导致的,不要怕,逐个解决其中的与当前业务逻辑最相关的对象,其他的对象可能随之就一起解决掉了,所以优先解决业务对象以及与问题复现场景下最强相关的对象的引用逻辑,其余对象逐步再进行优化。

  5. 结语

    问题通常会在开发的过程中逐渐积累,到最终暴露出来时可能已经涉及了多个模块、多种逻辑,各种逻辑互相耦合,导致分析的难度大大增加。

    这种情况下,我们建议把性能相关的工作也能做到平时,在开发态也去关心程序的性能问题。例如,刚写了一个很长的引用关系、增加了一些注册实例的逻辑或者做了一些父子组件的变量传递,这种时候就可以去结合逻辑自己设想一下,会不会引发一定的性能问题,甚至可以在平时就用调优工具来自测试。这样做到每个开发阶段都保证了性能的可靠,那么在项目日益增大的同时,性能问题也不会严重到离谱、无法分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/763281.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL架构和性能优化

文章目录 一、MySQL架构架构图存储引擎MyISAM引擎特点InnoDB引擎特点管理存储引擎 二、性能优化索引索引管理EXPLAIN 工具使用profile工具 监控 一、MySQL架构 架构图 存储引擎 MySQL提供了多种存储引擎供用户选择,每种存储引擎都有自己的特点和使用场景。 InnoDB…

算法刷题之路之链表初探(二)Leecode21合并两个有序链表

算法刷题之路之链表初探(二) 今天来学习的算法题是leecode141环形链表,是一道简单的入门题,话不多说!直接上! 条件(Leecode21) 重点!!! 我直接把…

primetime中cell和net的OCV

文章目录 前言一、Cell OCV1. POCV coefficient file2. POCV Slew-Load Table in Liberty Variation Format(LVF lib) 二、Net OCV三、如何check OCV是否已加上?总结 前言 在生产中,外界环境的各种变化,比如PVT&#…

代码随想录第40天|动态规划

完全背包 完全背包物品可以无限使用 01背包核心代码 01背包中的二维dp数组的两个for遍历可颠倒, 而一维dp数组的一定先遍历物品再遍历背包容量状态转移方程(背包容量一定为递减) 完全背包核心代码 (只在完全背包中一维dp数组嵌套顺序可颠倒, 实际题目需要确定遍历顺序) 状…

云计算与生成式AI的技术盛宴!亚马逊云科技深圳 Community Day 社区活动流程抢先知道!

小李哥最近要给大家分享7月7日在深圳的即将举办的亚马逊云科技生成式AI社区活动Community Day ,干货很多内容非常硬核,不仅有技术分享学习前沿AI技术,大家在现场还可以动手实践沉浸式体验大模型,另外参与现场活动还可以领取诸多精…

API-本地存储

学习目标: 掌握本地存储 学习内容: 本地存储介绍本地存储分类存储复杂数据类型 本地存储介绍: 以前我们页面写的数据一刷新页面就没有了,是不是? 随着互联网的快速发展,基于网页的应用越来越普遍,同时也…

中医药文化传承进校园活动授牌仪式在石家庄主办举办

青春闪“药”,我心向党。2024年6月30日,由河北省药品医疗器械检验研究院主办的”中医药文化传承进校园活动在石家庄主办。来自河北省各地24所学校作为示范学校现场接牌。 河北省科协科普部部长范玉鑫、河北省教育厅学位管理与研究生处副处长耿立艳、河北…

Springboot项目实训--day1

目录 一、软件安装 二、软件的简单了解 三、基础知识应用 1、四个常用注释 2、尝试新建类 3、控制反转(IOC容器) 4、返回数据给浏览器 5、浏览器传回数据给服务器 易错点 一、软件安装 需要安装的软件是idea专业版,刚使用的时候可以使…

mac|浏览器链接不上服务器但可以登微信

千万千万千万不要没有关梯子直接关机,不然就会这样子呜呜呜 设置-网络,点击三个点--选择--位置--编辑位置(默认是自动) 新增一个,然后选中点击完成 这样就可以正常上网了

Python 异常

文章目录 捕获异常捕获常规异常捕获指定异常捕获多个异常 else语法finally语法异常的传递 捕获异常 假设某处可能会出现异常,提前做好准备。 捕获常规异常 所有的异常都会被捕获,不指定异常。 语法: try:可能出错的代码 except:出现异常后…

Open3D 点云快速全局配准FGR算法(粗配准)

目录 一、概述 1.1原理和步骤 1.2关键技术和优势 1.3应用场景 二、代码实现 2.1 关键代码 2.1.1.函数:execute_fast_global_registration 2.1.2调用registration_fgr_based_on_feature_matching函数 2.2完整代码 三、实现效果 3.1原始点云 3.2粗配准后点…

写代码,为什么还需要作图?

引言 古人云 :一图胜千言,闲人说:无图无真相。 在日常的聊天工具当中,无论是使用微信,还是钉钉。使用图片或表情包的频次越来越高,那是为什么呢?其实在互联网没有那么发达的时候,我…

算法题笔记

主要记录python的力扣题解 参考的优质网站: 算法通关手册(LeetCode) | 算法通关手册(LeetCode) (itcharge.cn) 代码随想录 (programmercarl.com) 2024.6.28 题目:轮转数组 官网连接:189. …

Linux环境安装配置nginx服务流程

Linux环境的Centos、麒麟、统信操作系统安装配置nginx服务流程操作: 1、官网下载 下载地址 或者通过命令下载 wget http://nginx.org/download/nginx-1.20.2.tar.gz 2、上传到指定的服务器并解压 tar -zxvf nginx-1.20.1.tar.gzcd nginx-1.20.1 3、编译并安装到…

武汉星起航:跨境电商流量红利爆发,2023年出海企业迎突破增长

在数字时代的浪潮中,中国跨境电商以惊人的爆发力崭露头角,成为全球贸易的璀璨新星。2023年数据显示,跨境电商出口额高达1.83万亿元,同比增长19.6%,这一显著增速不仅刷新纪录,更为众多出海企业带来了前所未有…

vscode搭建suricata调试环境

一、环境 windows10 wsl2 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.2 LTS Release: 20.04 Codename: focal二、编译 2.1 下载源码 wget https://www.openinfosecfoundation.org/download/suri…

配电智能网关赋能电力系统智能化运行维护

随着智能电网和物联网技术的不断发展,两者之间的融合应用成为电力行业的重要趋势。配电智能网关作为连接两者的关键设备,在智能电网的物联网应用中发挥着重要作用。 配电智能网关能够实现对电力系统的实时监控、数据采集、远程控制等功能,为…

【Vue】微信禁止打开,可弹出提示:请用360、搜狗浏览器的极速模式打开。

需求 某网站链接,使用微信端打开,某些材料自动下载会造成泄密。所以添加限制:微信禁止打开,可弹出提示:请用360、搜狗浏览器的极速模式打开。 处理前 微信访问该链接,点击【继续访问】可直接跳转到该网站 处…

苍穹外卖项目 常用注解 + 动态sql

常用注解 常见的注解解析方法有两种: 编译期直接扫描:编译器在编译 Java 代码的时候扫描对应的注解并处理,比如某个方法使用Override 注解,编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。运行期通过反射处理&…

ROS2使用C++开发动作通信

1.开发接口节点 cd chapt4_ws/ ros2 pkg create robot_control_interfaces --build-type ament_cmake --destination-directory src --maintainer-name "joe" --maintainer-email "1027038527qq.com" mkdir -p src/robot_control_interfaces/action touch…