应用可靠性与性能不给力?HarmonyOS HiViewDFX 了解一下
作为基础软件服务子系统的 HarmonyOS HiViewDFX(以下简称 HiViewDFX)框架,是 HarmonyOS 的公共基础设施。包括日志、事件、跟踪、故障管理及观测剖析五大部分,同时也提供了故障检测、定位和性能观测剖析的开发套件,以及将端侧数据直接对接云侧大数据质量分析平台和 IDE(Integrated Development Environment, 集成开发环境)调试调优工具。为应对应用开发难题,HiViewDFX 提供了高保障能力。
HarmonyOS HiViewDFX 框架图
一、HiViewDFX 介绍
一般地,捕获异常信号需要自行增加捕获异常的机制,通过信号来感知异常及采集对应的异常日志,但是往往这类信息无法有效的与系统信息关联。
HiViewDFX 为应用开发者提供了具有轻量级故障检测、精准的故障定位日志以及快速恢复功能的开发套件,能够迅速提高应用的可靠性。
如下图所示,在 HarmonyOS 系统中首先内置崩溃、泄漏、卡死等轻量级故障检测器,用来记录应用在系统侧的异常状态。
其次,在应用程序框架内及运行时增加了异常捕获能力,使得系统和应用能够分层检测和记录异常信息,通过开放查询、订阅、恢复三个 API(Application Programming Interface, 应用程序编程接口)提供给开发者。
HarmonyOS 应用异常处理框架图
在应用崩溃和卡死的时候,HiViewDFX 提供的精准日志定位功能能够详细地记录异常发生时的日志。
HiViewDFX 提供了对应的应用异常日志查询接口,将 JS_CRASH, CPP_CRASH, APP_FREEZE 这三类故障日志提供给开发者,并且是结构化的日志信息,开发者可以从反馈的信息中快速获取到故障的相关信息。
为给用户提供更佳的体验,在日志信息反馈异常数据的基础上,HiViewDFX 提供了应用快速恢复的框架(如下图),当系统感知到 JS_CRASH, CPP_CRASH, APP_FREEZE, KILL 等故障之后,能快速通知应用,应用将之前的状态进行保存,而后系统会自动拉起应用,然后恢复到故障前的原界面。
应用恢复框架图
二、HIViewDFX 相关工具介绍
HiViewDFX 的工具入口---Insight,是 DevEco Studio 中的插件,拥有众多系统能力支撑,如图所示,有调试连接器、HiTrace、HiPerf 以及 HiProfiler 框架。
HiViewDFX 提供的系统能力包含日志、事件、分布式跟踪、故障等。
HiViewDFX 调试调优架构图
接下来,就让我们一起了解下 HiViewDFX 提供的部分工具吧!
1)调试连接器
如下图所示,调试连接器是连接上位机和下位机的通道,通常用做嵌入式开发,常用的连接工具,比如,基于串口或者网口的 Telnet、SSH 等。
HarmonyOS 面向不同形态的设备时,这些设备可能不具备网口或者 USB 端口,只有一个串口,要支持这个,串口上需要具备 Shell 和文件 IO 等功能。有了调试连接器作为中转,就可以让开发者使用的 IDE 和其他工具脚本无需面临硬件的复杂性,更好的关注调试和调优本身。
调试连接器原理示意图
2)HiTrace
如下图所示,HiTrace 工具用于追踪进程轨迹,进行程序性能分析,支持内核 FTrace 预置埋点和用户态打点。
在性能分析中,Trace 是最常用的方式,可以说 Trace 就是性能的日志,把 Trace 按照模块分门别类,这就是 Trace 的 Tag。例如,Sched 是操作系统内核的调度信息打点;Ability 是 Ability 模块在用户态的关键生命周期打点。
假设定位某应用掉帧的问题,在分析时,打开 Graphic、Ability、Sched 等 tag 点,可以在 Insight 里面分析应用在送显、图形模块绘制相关的耗时。
HiTrace 工具原理示意图
3)HiPerf
如下图所示,HiPerf 是为开发者提供的采样调优分析工具,通过采样的方式,可以采集 CPU PMU、Tracepoints 以及程序热点函数信息,并且和 Insight 联动,提供离线和实时分析的能力。
HiPerf 采集定位过程中会遇到一个难点:使用跨编程语言,在程序运行时,可能会存在一些跨语言的调用。例如,从 JS 调用 NAPI 到 C++接口等。
因为是抽样的调用栈采集,如果只采集其中一种语言的调用栈会导致两个语言之间的耗时数据无法同步,从而产生冲突,影响性能问题的度量和定位,所以在调用栈采集的时候进行缝合。
HiPerf 工具原理示意图
如下图所示,这段 JS 代码调用了三个内存相关的数据获取接口,均是 NAPI 实现的 NATIVE 接口。
在 HiPerf 中,首先采集 NAPI 调用 JS 的调用栈信息,当采集到一个 C++的调用栈时,此时栈顶是函数 NativeFunctionCallBack()的 NAPI 回调,则这个 NATIVE 调用栈就可以和前一次采集到的 JS 调用栈合并,最终拼接出一个完整的调用栈。
NAPI 调用中 JS-CPP 栈缝合示意图
除了上述系统内置的分析点,开发者也可以通过 HiTrace 接口增加自定义的性能分析打点。
如下列代码所示,HiTraceMeter 的接口比较简单,找到一段流程的开始和结束,加上 Trace 打点,就能在 Insight 中看到 Start-End 的耗时。
HiTrace API 介绍及开发样例图
4)HiProfilerHiProfiler
框架是基于 HiViewDFX 基础能力构建的一个插件集,可以为 Insight 提供调优数据采集。该组件整体分为 PC 端和设备端两部分。
PC 端最终作为 DevEco Studio 的插件进行发布,内部主要包括分为 UI 绘制、设备管理、进程管理、插件管理、数据导入、数据存储、 数据分析、Session 管理、配置管理等模块。
设备端主要包括命令行工具、服务进程、插件集合、应用程序组件等模块。设备端提供了插件扩展能力,对外提供了插件接口,基于该扩展能力可以按需定义自己的能力,并集成到框架中。
HiProfiler 框架
三、如何查询内存信息
操作系统对内存是分级定义的,从物理地址空间到虚拟地址空间,再分为用户态和内核态。应用内存调优分析的时候,还需要分解到虚拟地址、Ark JS 的内存、NATIVE 的内存、字体图标等资源、So 的映射、线程栈等,这些都属于内存观测的范围。
HiViewDFX 提供了 HiDumper 工具,作用是系统信息查询,它提供了系统版本、CPU 占用率、内存以及 Sa 信息,开发者可以使用 HiDumper 来分析应用的内存(如下图)。开发者分析内存比较关注的是 Ark JS Heap 以及 NATIVE Heap、Pss、Dirty 这些指标,如果程序有内存泄漏或者一般的内存膨胀的问题,可以看到这些值会不断变大。
HiDumper 查看内存信息示意图
如果应用要在程序中监控内存,可以使用这组 HiDebug 接口(如下列代码所示),前三个接口是 NATIVE 内存分配器的统计信息,可以获取 NATIVE 分配器的总大小、分配大小和可用大小,后三个接口是从系统 Smaps 获取的统计信息,注意这两个信息不是一个维度上的,不能做数据的等同,在使用场景上也有差异。
HiDebug 接口示意图
分配器的信息经常用于统计程序中对 Native 内存的分配情况,不代表这些内存实际被使用,这部分内存是开发者可以控制且可以进行优化的。
而系统 Smaps 统计信息,常用于程序感知自身内存的实际占用大小,这个大小经常受到分配器延迟释放、系统延迟回收、Copy-on-write、分配器 MetaData 额外损耗等,造成统计出来的内存信息和分配器控制的内存不完全等同,往往不能作为内存优化的直接依据,而是作为内存压力统计的依据。
四、如何进行内存调优分析
我们通过信息查询得知了内存的大小信息,那么如何进行内存分析呢?
如下图所示,右侧部分是开发者使用 Insight 进行分析的样例。
首先分析泳道图上的内存曲线,得到三类数据,JS、Native 和虚拟内存,它们采集的分配信息基本都比较相似。例如,图中分配信息部分,名字和调用栈,是区分一块内存的重要信息,地址和大小是一块内存的基本信息。引用关系可以帮助我们建立内存之间的关系树,帮助我们更快找到内存的引入点。分配时间则可以帮助开发者了解哪些内存会长时间存留,长时间存留的内存是需要重点关注的。
内存分析数据采集原理图
另外,虽然虚拟内存在 64 位上可能不是一个痛点问题,但是在 32 位程序上经常会导致问题。32 位程序的地址空间只有 4GB,如果是 32 位内核,那么用户态一般情况只有 3GB 地址空间,这种情况下开发者需要关注虚拟内存的使用情况,HarmonyOS 的做法是在 Mmap 的地方进行 Hook,拿到分配的调用栈,并且对系统映射的绝大多数匿名页都进行了命名。因此不论是文件页还是匿名页,在分配信息中都能看到页的命名信息,这对于内存分析非常有帮助。
以上就是 HiViewDFX 提供的可靠性和性能优化调试调优能力的相关介绍了,欢迎广大开发者使用 HiViewDFX 框架来开发一个高可靠高性能的应用!
评论