HarmonyOS AppFreeze 怎么排查:主线程卡住、FaultLog 证据和耗时任务怎么拆

HarmonyOS AppFreeze 怎么排查:主线程卡住、FaultLog 证据和耗时任务怎么拆 HarmonyOS 页面偶尔点不动最怕的不是报错而是没有明显报错。按钮还在页面也还在但点击、滑动、返回都没反应。很多时候这不是某个组件坏了而是主线程被同步任务占住了。这次只拆 AppFreeze 排查这一个问题页面为什么像卡死一样没有响应证据从哪里看代码怎么改。官方文档里提到 AppFreeze 是应用长时间不响应用户操作DevEco Studio 也有 FaultLog 入口真正排查时关键不是背概念而是把“触发动作、卡住时间、耗时任务、修复验证”连起来看。先看问题怎么出现最常见的坏写法是在页面事件里直接做大量同步计算或者一次性处理很大的数组。Button(生成统计).onClick((){constresult:Summary[][]for(leti0;i200000;i){result.push(buildSummary(i))}this.summaryListresult})这段代码看起来只是“点一下按钮生成数据”但它把计算、组装、状态更新都塞进了点击回调。数据量小的时候没问题数据量一大页面就会出现几类现象点击以后按钮没有立即反馈列表滑动卡一下才动返回键延迟日志里没有明确业务错误但 FaultLog 里能看到冻屏或主线程卡顿线索。这类问题不能只靠“我感觉页面有点卡”判断要把耗时任务拆出来验证。先把版本和验证环境说清楚这篇按 HarmonyOS 5.0 及以上的应用排查思路来写工具侧按 DevEco Studio 6.0 的 FaultLog 和性能排查入口来理解。示例代码不绑定某个具体页面重点是复现“主线程被同步任务占住以后页面交互为什么排队”的现象。验证环境我按三类证据看一是按钮点击后定时器是否被延迟二是任务拆块以后最大单块耗时是否下降三是 FaultLog 或耗时日志里能不能对上触发动作。只有这三件事能对上才说明不是随便改了一段代码而是把卡顿链路拆清楚了。案例一同步任务把事件循环堵住先用一个最小复现脚本模拟问题。定时器本来 10ms 后应该执行但中间塞了一个 180ms 的同步循环结果定时器只能等主线程空出来才执行。functionblockMainThread(ms:number){conststartDate.now()while(Date.now()-startms){Math.sqrt(Math.random()*100000)}}验证结果{mainThreadBlockedCase:{expectedTimerMs:10,actualTimerDelayMs:180,conclusion:timer-delayed-by-sync-work}}这个结果说明一件事只要同步任务占住主线程后面的点击、定时器、页面刷新都只能排队等。AppFreeze 的排查思路也是一样先找“谁长时间霸占主线程”。案例二把大任务拆成小块如果这段任务必须在页面侧做至少不要一次性跑完。可以拆成小块中间让出执行机会。asyncfunctionrunInChunks(total:number,chunkSize:number){letprocessed0while(processedtotal){constendMath.min(processedchunkSize,total)for(letiprocessed;iend;i){buildSummary(i)}processedendawaitnewPromisevoid((resolve)setTimeout(resolve,0))}}验证里把 120 万次计算拆成每次 6 万条{chunkedWorkCase:{elapsedMs:103,maxChunkMs:5,processed:1200000}}总耗时还在但每一小段占用时间被压下来了。页面不会因为一个超长同步任务一直没有机会处理输入。几种处理方式怎么选方案适合场景不适合场景拆小块执行数据处理不算特别重只是一次性太集中计算本身很重拆块后仍然卡TaskPool一次性计算、排序、过滤、聚合需要长期通信或持续状态同步Worker长时间任务、持续通信、可独立维护状态只是几百条数据的小计算RDB 分页/索引数据来自本地数据库内存里临时数组处理我一般先看任务来源如果问题来自数据库查询先优化查询如果问题来自内存聚合考虑 TaskPool 或分块如果是持续任务Worker 比硬塞 TaskPool 更合适。FaultLog 里重点看什么排查时不要只盯一行错误。更有用的是把页面操作、日志时间和 FaultLog 时间对齐检查点看什么触发动作用户点击、滑动、进入页面还是后台恢复卡住时间卡顿是否集中在某个操作后主线程线索是否有长时间同步任务、布局计算、密集循环业务日志同一时间是否开始了批量处理、查询、图片解析修复验证拆分任务后同样操作是否还能复现如果日志里只写start和end中间没有任务规模、分页参数、数据条数排查会很吃力。建议关键路径日志至少带上scene、count、costMs、traceId。修复以后怎么复测这类问题修完以后不能只看“点一下好像不卡了”。我一般会把复测拆成三步第一步用同一批大数据再次触发原来的按钮或列表操作第二步把页面滑动、返回、切换页签这些交互都跑一遍看有没有明显延迟第三步对比修改前后的耗时日志确认单次同步占用已经降下来。如果用了分块执行要重点看每个小块的最大耗时而不是只看总耗时。总耗时可能还是 100ms 左右但只要每一小块都控制在几毫秒到十几毫秒以内页面就有机会处理输入、动画和刷新。如果把任务丢到 TaskPool 或 Worker还要补一层失败兜底任务取消、页面销毁、数据版本过期时结果不能再回写到已经离开的页面。复测项通过标准大数据按钮点击点击后页面仍能响应返回和滑动列表滚动滚动过程中没有连续白屏或长时间停顿耗时日志单次同步片段不再长期占住主线程页面销毁异步结果回来后不会写入已销毁页面这张表的作用不是写文档好看而是逼自己把“代码改了”变成“问题真的复现不了”。AppFreeze 最麻烦的地方就在这里它经常不是语法错而是任务边界没守住。以后怎么避免我会把这类问题收成几条规则页面点击回调不要直接放大循环列表数据量超过阈值时先分页、索引或分块图片解析、排序、聚合这类任务不要和 UI 反馈绑死耗时任务要记录数据量和耗时不要只记录成功失败修改后要用同一批数据复测不能只看代码改得顺不顺。AppFreeze 排查的核心不是“看到冻屏日志再害怕”而是平时写代码就把主线程边界守住。页面越复杂越要把数据处理、UI 状态和日志证据拆开。参考资料HarmonyOS Application Freeze Detectionhttps://developer.huawei.com/consumer/en/doc/harmonyos-guides/appfreeze-guidelinesHarmonyOS FaultLog 文档https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-fault-logDevEco Studio 6.0 新增能力说明https://developer.huawei.com/consumer/en/doc/harmonyos-releases/deveco-studio-new-features-600