怎么运用DevEco Studio功能调优东西Profiler定位使用内存问题
鸿蒙。运用开发进程中,或许因为种种原因导致运用内存未被正的运用或许偿还至。操作体系。,然后引发内存反常占用、内存走漏等问题,终究导致运用卡顿乃至溃散,严重影响用户体会。
DevEco Profiler是集成在DevEco Studio中的一款原生鸿蒙运用功用优化东西,能够辅佐。开发者。高效完结鸿蒙运用的功用问题定位与优化。在集成开发环境DevEcoStudio中能够以如下办法翻开DevEco Profiler:
在DevEco Studio顶部菜单栏中挑选“View->Tool Windows ->Profiler”。
在DevEco Studio底部东西栏中单击“Profiler”。
按“Double Shift”或许“Ctrl+Shift+A”翻开查找功用,查找“Profiler”。
DevEco Profiler中供给了针对鸿蒙运用内存问题的场景化剖析模板Snapsho。tI。nsight与Allocation Insight,能够用于剖析ArkTS以及Native内存,协助开发者高效定位处理内存问题。下面将从辨认问题、定界定位、优化验证三个方面来对DevEcoProfiler定位内存问题的办法进行介绍。
辨认内存问题。
1.1 监控运用内存。
当运用的某项功用开发完结时,能够运用DevEco Profiler的实时监控功用对运用的各项资源进行监控,其间就包括运用内存资源。详细运用办法见功用问题定界。
功用问题定界:https://developer.huawei.com/consumer/cn/doc/。harmonyos。-guides-V13/realtime-monitor-V13?catalogVersion=V13。
实时监控界面所展现的是运用在运转进程中实践所运用的物理内存(ProportionalSet Size, PSS)、其他进程的物理内存占用以及操作体系的闲暇内存,泳道的蓝色部分展现了当时进程的物理内存占用状况及趋势,左边饼图则展现了当时时刻的瞬时内存运用数据。
此刻,咱们能够正常地操作运用,调查在当时功用运转进程中的运用内存改变状况,开端判断是否存在内存问题。当发现在一段时刻内运用内存没有显着添加或许在内存上涨后又逐步回落至正常水平,则根本能够扫除运用存在内存问题;反之,假如运用内存占用显着与预期值不符合、在一段时刻内不断上涨且无回落或许内存占用显着添加超出预期,那么则可开端判断运用或许存在内存问题,需求进一步剖析。
1.2 开端定界内存问题。
当从实时监控页面开端判断运用或许存在内存问题的时分,进一步地能够运用AllocationInsight或Snapshot Insight的。Mem。or。y泳道。来抓取运用内存在问题场景下的详细数据以及改变趋势,开端定界问题呈现的方位(NativeHeap/ArkTS Heap/dev段等)。
在当时进程下,录制内存数据时需求将Allocation Insight或SnapshotInsight中的其他泳道去除勾选,仅录制Memory泳道的数据。(注:因为其他泳道会敞开对内存分配、内存目标等数据的抓取,这些功用会带来额定的开支,或许会对咱们开端定界问题产生噪音,影响剖析,故先扫除录制)。
在Memory泳道的录制进程中,不断操作运用在问题场景的功用,将问题扩大,便于快速定界问题点,参阅录制进程中的运用内存占用曲线,当曲线的上涨幅度到达必定巨细时即可完毕录制。
录制完结后,能够翻开Memory泳道,检查运用内存分段的运用状况,也能够点击泳道上的options下拉框,自行挑选想要重视改变状况的内存类型。
一起,能够选中Memory泳道或其任一子泳道(直接选中泳道时概况区域会展现完好的泳道数据)来检查在每个采样点的详细运用内存占用数据(注:概况区域数据选用PSS的维度衡量,数据近似于运用`hidumper --mem $。pi。d`的榜首列PSS值)。当鼠标左键单击选中表格中某一行的数据时,对应的泳道大将展现出当时的时刻刻度线,便利快速定位内存改变的时刻方位。
通过检查Memory的子泳道内存分类以及概况区域的内存详细占用,咱们能够大致定界出有哪些方位的内存或许存在问题。例如上图中从Memory的子泳道数据图中能够看到,FilePageOther/Native Heap/ArkTS Heap均有较大的添加,因而能够以这三个方面的内存运用作为切入点,来进一步剖析问题的根因。
定位内存问题。
从1.2节中的剖析可知,当时运用内存的添加首要会集在FilePage Other/NativeHeap/ArkTS Heap这三个部分,那么需求运用进一步的剖析办法对这三个方面的内存进行剖析,定位内存上涨的根因。
在剖析鸿蒙运用的内存问题时,能够将鸿蒙运用的内存大体分为两部分,方舟虚拟机内存和Native内存:
1. 方舟虚拟机内存:由方舟虚拟机管控的运用内存,同其他的虚拟机内存(例如。Java。)办理战略相似,开发者能够运用并操控的内存根本会集于虚拟机堆上,在方舟虚拟机上被称作ArkTSHeap,这部分内存遭到方舟虚拟机的管控。
2. Native内存:这部分内存首要是运用运用到的一些触及Native的API所请求的内存以及开发者自己的Native代码所请求运用的堆内存(一般是C/。C++。),这部分内存需求开发者自己去办理请求和开释。
因为两种内存的运用办法和办理办法不尽相同,因而在对这两类内存的剖析进程中所运用的办法也有比较大的差异,下面将从这两个方面别离介绍剖析办法。
2.1 ArkTS内存问题。
2.1.1 ArkTS内存办理。
首要针对ArkTS Heap,因为该部分堆内存遭到方舟虚拟机的办理,能够对堆内存进行废物收回(GarbageCollect,GC)和拍照快照(HeapSnapshot或HeapDump,简称dump)以反映出瞬时的全量堆内存运用及散布状况,因而这部分内存的问题剖析手法首要是对堆dump进行引证联系剖析,剖析走漏目标无法被GC收回的原因。
不同于引证计数算法,方舟虚拟机选用可达性剖析的机制来办理目标是否可被废物收集器收回,因而针对方舟虚拟机内存的剖析办法首要会集于目标的引证剖析,即剖析哪些目标引证联系是过错的或许反常的,然后导致了走漏目标被长时刻持有无法被GC,终究通过免除强引证联系的手法来处理内存走漏问题。如下图1所示,蓝色的目标节点表明在内存引证剖析中该目标GCRoot引证可达,其他目标GC Root引证不可达,引证不可达的目标在GC中能够被虚拟机收回。
图1 目标可达性剖析。
2.1.2 ArkTSHeap剖析。
针对虚拟机的内存问题剖析一般都会集在对dump的目标散布及引证联系的剖析上,方舟虚拟机也不破例,这儿在DevEcoProfiler上供给了Snapshot Insight来对方舟虚拟机的堆内存进行剖析。
在运用Snapshot剖析时,一般会运用三快照技能(Three Snapshot。 Te。chnique),通过内存快照的比照视图将某两次快照之间分配且依然驻留的内存挑选出来,这些目标中的一部分就或许是导致内存走漏的目标。通用的流程为:
翻开运用,初始化场景(触发GC)->拍照榜首次Snapshot作为基准 ->多(N)次触发内存走漏操作 ->拍照第2次堆快照 ->触发主动GC->拍照第三次堆快照。
因为方舟虚拟机供给了在获取堆快照之前主动GC的功用,因而咱们能够将上述流程简化为两步,一起加上Profiler的录制功用,全体流程为:
翻开运用,初始化场景->敞开录制Snapshot Insight->拍照榜首次Snapshot作为基准 ->多(N)次触发内存走漏操作 ->拍照第2次堆快照->完毕录制。
录制完结后,会得到如下图所示的数据。
录制进程中,咱们收集了两次堆快照,对应在Profiler的界面上便是两个紫色的条块,每一个条块内的数据都是当时的虚拟机堆快照。条块上的数字巨细代表的是虚拟机堆内存的实践占用。
因为在每次拍照堆快照之前,虚拟机都会触发GC,所以理论上堆快照内存在的目标都是当时虚拟机现已无法GC掉的目标,所以咱们能够将两个堆快照进行比较,来检查哪些目标是咱们在触发问题场景时新增了且不能开释的。
点击Snapshot Insight面板的Comparison页签,将两次Snapshot进行比较,如下图。图中数据的意义为以Snapshot2作为基准,Snapshot2比照Snapshot1的数据改变量。
即便是比较视图,东西也十分多,怎样剖析呢?
还记得上面说的操作。N次。吗,在触发内存问题场景时将问题触发N次,在比较视图中首要就去找与N强相关、与事务代码强相关的constructor,首要来剖析这些目标是否正常。
首要介绍一下Snapshot比较视图中各项数据的意义,如下图,愈加详细的也能够参阅内存走漏剖析或许运用Snapshot Insight剖析ArkTS内存问题。
内存走漏剖析:https://developer.huawei.com/consumer/cn/doc/。harmony。os-guides-V13/ide-insight-session-snapshot-V13?catalogVersion=V13。
运用Snapshot Insight剖析ArkTS内存问题:https://developer.huawei.com/consumer/cn/forum/topic/0207154775311720043?fid=0109140870620153026。
在找到相关的事务相关的目标后,能够从references里边一层层去寻觅、排查在引证链上的可疑目标(一般指与事务代码相关的目标,尤其是xxx in com.xxx.yyy这种显着是事务运用到的目标的方位)。
在排查时,能够首要往两个方向:
1)Distance逐步减小;
2)引证链上都是事务相关的目标。
从这两个维度去剖析入度引证链,找出那些事务逻辑上应该开释可是实践并没有开释的目标及其引证联系。,从这些引证联系上来排查是否有不合理的强引证导致的内存无法开释的问题,从而处理内存走漏问题。
详细的事例能够参阅:运用SnapshotInsight剖析ArkTS内存问题。
运用Snapshot Insight剖析ArkTS内存问题:https://developer.huawei.com/consumer/cn/forum/topic/0207154775311720043?fid=0109140870620153026。
2.2 剖析Native内存。
其次针对Native Heap,因为该部分堆内存仅由开发者自行操控分配开释,无法运用相似虚拟机的dump手法来剖析全体的堆内存运用状况,仅可运用Profiler抓取到录制进程中的运用内存分配和开释事情,因而需求开发者通过内存分配/开释事情以及内存分配栈等。信息。自行找到代码中的内存请求和开释点来承认是否存在请求、开释不配对导致的内存走漏问题。
内存剖析模板Allocation供给了该才能,运用该模板能够抓取到经由体系根底库分配的Native部分内存,剖析分配/开释的匹配逻辑,界面如下图。
在开端录制前,需求先了解一些该模板的。作业原理。以及相关的装备。参数。,以承认能够抓取到运用中或许存在的内存问题。
Allocation模板通过hook根底库中的某些函数调用来获取每次内存分配的数据,并将这些数据回来至Profiler中,在Profiler中完好的展现这些内存的分配、开释数据以及相关的调用栈、库等信息。详细的运用介绍能够参阅这儿内存剖析及优化,下面就详细的运用流程做介绍。
内存剖析及优化:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/ide-insight-session-allocations-memory-V13?catalogVersion=V13。
2.2.1Native数据收集。
首要,是录制前的参数装备,最新版。本的装备页面如下,其间的装备项都是针对NativeAllocation这条泳道的,下面顺次介绍:
1)Statist。ic。s Mode、Sampling Interval:该项装备代表是否敞开计算方法收集数据,默许敞开。敞开后,数据会每隔SamplingInterval中设置的时刻从设备端汇总并回来,该方法下东西的收集功用会更好、负载更低、可收集的时刻也更长,可是会丢失掉精准的每次分配开释的内存信息;封闭该方法,会敞开概况收集方法,回来的数据中会给出每次内存分配的详细状况,包括内存分配地址、分配巨细、分配栈等信息。引荐。运用计算方法,如事务侧有需求也可酌情运用概况方法。
2)Filter Size:过滤内存巨细。该参数表明最小抓取的内存巨细,默许为1024bytes(1kb),内存分配时小于该巨细的内存分配信息不会被抓取到,运用可依据本身详细状况挑选该参数。该参数或许会明显影响运用功用,当该值过小且运用在分配很多内存的场景时(抓取的内存分配数据量巨大)或许会形成运用卡顿,因而主张挑选适宜的参数。
3)B。ac。ktrace Mode:内存分配栈回栈办法,默许FP回栈。FP回栈功用更好,默许敞开,但在某些特定场景下(例如so的编译参数操控),FP回栈或许失效,此刻可挑选DWARF回栈测验。
4)Record JS Stack:是否敞开JS回栈。当该开关翻开时,体系回栈时会主动从Native向JS层回栈,完结Native到JS的栈缝合,合适ArkTS/JS代码调用Native的场景。
5)JS Backtrace Depth、Native Backtrace Depth:内存回栈深度。代表最大的回栈层数,层数越大对功用开支越大,可结合事务动态调整。
注:当挑选了DWARF回栈后,JS和Native的回栈深度会变成一个框Backtrace Stack,其层数代表着JS与Native的一起回栈深度。
做好装备后,能够开端抓取问题场景的数据,牢记需求在保存数据并敞开录制之后,操作运用复现问题场景,并在问题复现完结后中止录制。(注:假如是运用计算方法,录制的完毕时刻需求是SamplingInterval即收集周期的整数倍,例如当收集周期是10s时,中止时刻主张在11s+/21s+/31s+,以此类推,留出余量给体系做数据处理与传输)。录制完结后界面相似下图。
其间泳道部分展现了当时的内存改变状况,Native Allocation泳道下方又触及两个子泳道AllHeap和All Anonymous VM,这两个泳道别离代表运用malloc和mmap函数分配的内存状况,下方的概况区域展现对应泳道的内存分配计算数据(Statistics页签)与内存分配栈(CallTrees)信息。
2.2.2Native数据剖析。
抓取到了问题场景的数据,接下来便是对问题数据的剖析。
首要,框选规模内的数据展现的是:在框选规模的起点之后及在框选规模的结尾之前的一切内存分配的数据。,这个逻辑很重要,会对剖析定论有很大影响,需求点重视。
接下来,在概况面板的左下角有一个下拉单选框,能够挑选当时概况区域展现的内存的数据,如下图所示:
1)All Allocations:框选的时刻段的一切分配内存信息。
2)Created & Existing:在框选规模的起点之后分配的,且在框选规模的结尾之前没有开释的内存数据。
3)Created & Released:在框选规模的起点之后分配的,且在框选规模的结尾之前现已开释的内存数据。
这三个选项能够依据详细的事务问题和诉求来承认。
第二个框中的Native Size和Native Library代表能够通过这两个维度:巨细和分配库的信息来做计算,一个是依照分配巨细。聚合。、另一个是依照分配该内存的库来聚合。
通过这个页签的计算信息、对未开释的数量、巨细等列排序后,能够大致剖分出内存呈现问题的状况以及场景,为剖析内存栈做一些提前准备。接下来能够把数据切换到CallTrees内存分配栈上。
该部分数据展现了详细的内存分配栈信息,内存问题一般都是在该部分通过栈帧信息找出相关的事务逻辑来定位。其间有两个点需求阐明:
1)栈帧中首要为Native栈,除了运用本身编译的一些so及带有部分。接口。信息的so信息外,其他体系库部分仅展现so库与函数偏移信息,若需求检查这部分信息,需求导入相应版别的带符号的so库。详细参阅根底耗时剖析中的离线符号解析末节。
根底耗时剖析:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/ide-insight-session-time-V13?catalogVersion=V13。
2)敞开Record JS Stack之后,部分栈帧中或许包括JS栈信息,JS栈信息一般对应着运用源码,双击能够跳转到代码行上。
注:一切Category上有高亮色的栈帧信息,都能够通过双击跳转到源代码地点的文件和代码行上(条件是翻开的工程是调优运用的相匹配的工程)。
同样地,在剖析调用栈的进程中,能够运用下方操作栏上的一系列功用,除了上述介绍过的AllAllocations挑选才能之外,在Native Allocation泳道的Call Trees页签中,能够通过底部的“Call Trees”和“Constraints”挑选框来过挑选和过滤内存分配栈。
Call Trees挑选框包括两种过滤条件:
Separate byAllocated Size:在内存分配栈完全相同的状况下,会依照每次分配栈请求的内存巨细将栈分隔;
Hide SystemLibraries:躲藏内存分配栈中的体系仓库。
Constraints挑选框也包括了两种过滤条件:
Count:依据指定的内存请求次数过滤内存分配栈信息;
Bytes:依据指定的内存请求巨细过滤内存分配栈信息。
事务方能够依据本身的事务状况与详细的问题场景来恰当运用这些数据挑选才能,一起在下方也供给查找功用,InvolvesSymbol Name查找框供给了针对函数调用栈的文本查找才能,能够快速查找栈帧信息与so库信息并方便跳转至对应方位。
别的,若表格的树状图不便于直观看出内存信息,能够运用Flame Chart火焰图开关,运用火焰图的方法来剖析内存分配或许存在的问题,如下图,火焰图中的条块长度越长,代表该调用栈分配的内存巨细越大。
2.2.3Native内存问题剖析。
在前面两个末节介绍了整个Native Allocation的运用及剖析办法,这儿简略介绍详细的问题剖析逻辑:
1. 录制问题场景的内存分配信息;
2. 从计算信息及内存分配栈检查在当时规模内未开释的内存信息(挑选Created &Existing),通过2.2.2节中介绍的各种剖析和挑选才能找出未开释的内存仓库,并将该仓库结合事务逻辑剖析;
3. 若触及ArkTS代码对Native的调用逻辑,可敞开Record JS Stack开关,将Native的内存栈回栈至JS层,简化剖析难度;
4. 通过这些问题栈帧信息映射到事务代码中,结合问题场景和代码剖析为何该部分内存未开释,找到问题点。
修正及验证。
当通过上述进程的流程剖析完运用的内存问题之后,根本上现已能够定位到问题产生的方位及相关的代码段,在此根底上结合事务逻辑对代码做修正,修正后从头编译推包到真机上,在相同的场景下测验复现问题,并运用实时监控或许Allocation/Snapshot模板的Memory泳道来监测运用内存占用状况,以承认问题是否还存在。
总结。
问题不是一朝一夕呈现的,一般问题会在开发的进程中逐步堆集,到终究露出出来时或许现已触及了多个模块、多种逻辑,各种逻辑相互。耦合。,导致剖析的难度大大添加。
这种状况下,咱们主张把功用相关的作业也能做到平常,在开发进程中也去关怀程序的功用问题。例如,刚写了一段很长的引证联系、添加了一些注册实例的逻辑或许做了一些组件间的变量传递,这种时分就能够去结合逻辑自己想象一下,会不会引发必定的功用问题,乃至能够在平常就用调优东西来。检测。一把。
这样做到每个开发阶段都确保了功用的牢靠,那么在项目日益增大的一起,功用问题也不会严重到离谱、无法剖析。
附录。
DevEco Studio。下载。链接:https://developer.huawei.com/consumer/cn/deveco-studio/。
DevEco Profiler官方辅导文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-insight-V5。