伴随着社区 3.41 版本的正式发布,面向 Flutter 鸿蒙开发者,我们规划了合计 11 篇 DFX 系列文章,按问题类型逐个展开,覆盖日志、崩溃、卡死、丢帧、时延、功耗、事件、内存、纹理、多设备等主题,带你整体了解 Flutter 鸿蒙在 DFX 上是怎么做的、怎么用的。本篇作为开篇,先打好基础。

一、DFX 是什么

DFX是为了提升软件质量属性的设计,目前主要包括可靠性和可测试性两大部分。鸿蒙系统上具体功能包括了流水日志、分布式跟踪、卡死故障检测和系统事件埋点,用来帮助开发者了解系统运行状态、定位和恢复故障。

落到Flutter鸿蒙平台上就是内置了一套自我监控:应用在崩溃、卡死、卡顿、内存泄漏发生时,DFX自动把日志和事件记下来,开发者拿这些记录定位原因。

DFX的作用接近飞机的黑匣子:平时不显眼,出问题后靠它还原现场。

二、三件工具和一个通道

OHOS 提供三套诊断工具,职责不重叠:

工具记什么类比
HiLog系统日志,逐行文本浏览器的 Console
HiAppEvent结构化事件,带参数Crashlytics的崩溃报告
HiTrace性能追踪,记录每帧耗时Android 的 Systrace

排查问题的第一步永远是抓HiLog-大部分问题的线索都在日志里。HiAppEvent 和 HiTrace 在你需要结构化分析信息或逐帧分析时会用上,对应分析工具可以使用DevEco Studio的Profiler工具或者开源的HiSmartPerf性能工具,这块比较专业了,后面有诉求可以专门写各专栏。

日志来自三个源头,过滤时用得上:

来源Tag典型内容
引擎内部(FML_LOG)映射到 HiLog崩溃堆栈、卡死检测、GPU 回收
平台 C++ 层XComFlutterOHOS_Native引擎初始化、NAPI 调用
ETS 嵌入层FlutterMethodChannel、插件异常、生命周期

一条命令看全部 Flutter 日志:

hdc shell hilog | grep -E "Flutter|XComFlutter|flutter"

这条命令把三个源头的日志一起筛出来,不确定问题类型时可以先用它。

再说下hdc(OHOS Device Connector),它是鸿蒙版的adb,负责在电脑和设备之间传文件、执行命令。后面所有命令都通过它执行,下面是三个常用的命令:

# 查看已连接的设备hdc list targets# 在设备上执行命令hdc shell <命令>
# 从设备拉取文件到电脑hdc file recv <设备路径> <电脑路径>

第一条确认设备在线

第二条是所有排查命令的载体

第三条把设备上的日志和 trace 文件拉回电脑分析

三、Flutter 鸿蒙应用通常的卡顿点在哪?

Flutter鸿蒙的卡顿问题,往往最终都定位以下三条线程上:

线程职责出问题时的表现
UI 线程运行 Dart 代码,构建 Widget 树界面完全冻结,触摸无响应
Raster 线程把 Widget 树绘制成像素,交给 GPU界面不更新,触摸可能有响应
Platform 线程和 OHOS 系统交互,处理触摸、系统消息平台通道阻塞,可能间接卡 UI

前三个阶段在 UI 线程,Dart 代码慢会在这里超时。

Composite 在 Raster 线程,大图、模糊、大量图层会让这里超时。

每个阶段可用的时间由屏幕刷新率决定,这个时间叫帧预算:

屏幕刷新率帧预算含义
60Hz16.6 ms每帧 16.6 毫秒内画完
90Hz11.1 ms每帧 11.1 毫秒内画完
120Hz8.3 ms每帧 8.3 毫秒内画完

某一帧没在预算内画完,这帧就丢了,用户看到的是「卡了一下」。帧预算的直观感受接近翻页动画书:每秒翻 60 页动画才连贯,某一页翻了 50 毫秒,画面就停一下。

到这里,卡顿排查的第一步已经明确:确认哪条线程超时

UI 线程超时查 Dart 代码的 build/layout/paint,Raster 线程超时查绘制复杂度,逐帧的分析方法和触摸到上屏的完整链路。

四、分清是哪一种「卡」

在Flutter鸿蒙应用开发中,用户口中的「卡」多数是这两个出了问题:

指标定义感受阈值
响应时延从触摸到首个画面反馈的时间超过 100ms 觉得迟钝
完成时延从操作到整个操作彻底完成的时间视场景而定

两者的成因不同:响应时延慢,多数是主线程被阻塞;完成时延慢,多数是数据加载慢或首屏构建太大。

五、故障速查清单

以下是梳理的一版故障速查清单,具体的讲解后续都会进行介绍,大家先期待下:

看到的现象可能的问题
应用闪退、崩溃Native 崩溃 / Dart 异常 / ETS 异常
应用卡死、无响应、点不动线程卡死(UI/Raster/Platform)
界面卡顿、滑动不流畅丢帧/JANK(帧率不够)
点了按钮反应慢、跟手性差响应时延过长(主线程被阻塞)
页面打开白屏太久才出内容完成时延过长(首屏构建/数据加载慢)
发烫、耗电快、CPU 持续高占用负载异常 / 后台功耗
内存占用过高、OOM 闪退Dart Heap 内存超限
黑屏、白屏、渲染异常GPU 上下文丢失
视频/相机画面黑屏、不更新、卡顿外接纹理问题
分栏不生效/避让失效/折叠屏异常多设备适配问题
不确定是什么问题先抓全量日志

六、万能第一步:把日志抓下来

破案要先保护现场,排查问题也是同理。

不管什么问题,先按四步把日志抓下来:

# 1. 清空历史日志,只留复现后的新日志hdc shell hilog -r
# 2. 复现问题(操作应用,触发 bug)
# 3. 抓取日志,Ctrl+C 停止hdc shell hilog > flutter_log.txt
# 4. 筛出 Flutter 相关内容hdc shell hilog | grep -E "Flutter|XComFlutter|flutter"

顺序也要关注下:先清理历史日志再复现,这样日志里只有本次问题的记录,搜索范围小得多,抓完的全量日志留底,筛过的日志用来定位。

已知问题类型时,直接按类型过滤,噪音会少很多。

常用的关键命令行分组如下:

# 崩溃(应用闪退)
hdc shell hilog | grep -E "Caught signal|Unhandled Exception|FLUTTER_DART_EXCEPTION|FLUTTER_ETS_EXCEPTION"
# 卡死(应用无响应)
hdc shell hilog | grep -E "FlutterWatchdog|not alive|HiCollie|THREAD_STUCK"
# 卡顿/丢帧(界面不流畅)
hdc shell hilog | grep -E "JANK|jank|missed|frame"
# 内存(OOM、内存占用高)
hdc shell hilog | grep -E "heap memory|memory|OOM|threshold"
# GPU(黑屏、白屏)
hdc shell hilog | grep -E "GpuReclaim|GPU|gpu"
# 外接纹理(视频/相机画面异常)
hdc shell hilog | grep -E "external_texture|ExternalTexture|NativeImage|DlImage|frame gate|VisibleArea|texture_id"
# 多设备适配(分栏、折叠屏等)
hdc shell hilog | grep -E "SplitView|split_view|avoidArea|displayFeature|foldStatus|device pixel ratio|windowSizeChange|LTPO"

界面卡顿但日志看不出问题时,就得抓性能 Trace了,简单一些可以用 Chrome 打开 chrome://tracing 加载进行分析:

hdc shell hitrace --trace_clock boottime -t 10 flutter -o /data/local/tmp/trace.ftrace
hdc file recv /data/local/tmp/trace.ftrace ./trace.ftrace

更专业的可以使用 HiSmartPerf 性能调优工具,使用方式和功能基本对标了Android 的Perfetto,性能领域专家可以重点关注下。

七、日志里搜什么:关键字与事件

日志打印后,可以按这张表搜关键字,快速判断问题类型:

关键字问题类型含义
Caught signal SIGSEGV引擎崩溃访问非法内存,比如空指针
Caught signal SIGABRT引擎崩溃内部断言失败或内存被破坏
Unhandled Exception:Dart 异常代码有未 try-catch 的异常
is not alive卡死某个线程 3 秒没响应
Dart heap memory usage exceeds threshold内存超限Dart 内存超过 1.5 GB
GpuReclaim + kAggressiveGPU 回收系统回收 GPU 资源(退后台时正常)
GpuReclaim + kRestoreGPU 恢复资源恢复中(回前台时正常)
Poll error:消息循环异常系统消息循环出错,可能导致卡死
AwaitVSync…failedVSync 失败垂直同步信号请求失败,可能导致不渲染
No DlImage available外接纹理纹理没有可绘制的画面(黑屏)
frame gate enabled外接纹理应用在后台,纹理帧被暂停(正常)
skip one frame外接纹理画面生产太快,跳过了一些帧

引擎自动上报的 HiAppEvent 事件对应同一套问题分类:

事件含义
FLUTTER_DART_EXCEPTIONDart 代码 bug 导致崩溃
FLUTTER_ETS_EXCEPTIONArkTS 插件代码 bug
OTHER_JANK某一帧渲染太慢
OTHER_JANK_STAT一段时间的丢帧汇总
OTHER_JANK_SCROLL滑动时某帧超过 50ms
FrameworkMemAnomalyDart 内存超过 1.5 GB
FLUTTER_THREAD_STUCK某个线程卡死
FLUTTER_GPU_CONTEXT_LOSSGPU 资源被系统回收
FLUTTER_ENGINE_CREATE / DESTROY引擎被创建或销毁

后三个是 FLUTTER_STABILITY_EVENT 的子类型,是通过 eventName 字段进行区分的,事件参数的完整说明后续篇章会细讲。

八、版本边界与文档索引

值得注意的是,部分上报能力有系统版本要求的,事件搜不到时先查这里:

功能最低版本低于此版本
HiAppEvent 事件上报API 18不生成事件,HiLog 仍可用
HiTrace 扩展接口API 19丢帧详情,Trace 不可用
内存异常上报(FrameworkMemAnomaly)API 26不上报事件,HiLog 仍可用

这个系列是结合了最近3.41版本发布整体规划的 ,共计 11 篇

01 开篇 → 02 日志抓取与过滤 → 03 崩溃定位 → 04 卡死冻屏 → 05 丢帧卡顿 → 06 滑动卡顿与时延深度 → 07 负载与功耗 → 08 DFX 事件字典 → 09 内存与 GPU → 10 外接纹理 → 11 多设备适配

期待下第二篇:日志抓取与过滤 - 从 hilog 到 HiTrace。

小伙伴们记得关注我,关注 CPF-Flutter 社区!
社区官网:https//atomgit.com/CPF-Flutter

“AI再牛,技术不能丢”

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐