使用冻屏增强日志定位繁忙类问题

📅 2026/6/30 12:46:07
使用冻屏增强日志定位繁忙类问题
本原创文章帖发布在华为开发者联盟社区欢迎开发者前往访问评论交流更多与该内容相关讨论请点击原帖查看使用冻屏增强日志定位繁忙类问题-华为开发者话题 | 华为开发者联盟概述用户在使用应用时如果出现点击无反应或应用无响应等情况并且持续时间超过一定限制就会被定义为应用冻屏AppFreeze即应用无响应。系统会检测应用无响应并生成AppFreeze日志供应用开发者分析。从API 21开始支持获取​AppFreeze的增强日志​。该日志通过采集整机及主线程的运行负载并抓取多份主线程调用栈帮助开发者知晓函数调用耗时。日志获取及规格可以参考AppFreeze应用冻屏检测-故障检测-Performance Analysis Kit性能分析服务-调测调优-系统 - 华为HarmonyOS开发者冻屏的两种成因类型特征传统栈追踪效果阻塞类线程因资源无法获得而挂起3s/6s栈能支撑锁定耗时任务繁忙类线程频繁执行业务逻辑仅靠2个瞬时栈无法锁定耗时函数传统方案的痛点当 ThreadBlock3s 和 InputBlock 事件的调用栈出现以下情况时传统日志难以定位问题• 系统栈 - 主线程全是系统栈• 瞬时栈 - 栈指向的函数并非真正耗时只是一个切面此时只能看到瞬时的调用栈片段无法确认具体哪个函数在耗时。增强日志的核心能力增强日志通过以下方式解决上述痛点1. 采集多份主线程调用栈 - 在采样周期内多次抓取调用栈2. 记录整机及主线程运行负载 - 辅助判断线程是否真正获得CPU执行时间3. 采样栈与耗时关联分析 - 从多次采样中识别耗时函数增强日志用法重点Step 1: 判断线程是否获得CPU执行查看 CPU耗时统计 部分CpuTime: 0 ms - 主线程实际运行时间 SyncWaitTime: 2995 ms - 主线程等待时间 StaticsDuration: 2995 ms - 统计总时间判断逻辑场景现象结论CpuTime ≈ 0SyncWaitTime ≈ StaticsDuration线程未获得CPU可能是等待锁、IO阻塞等阻塞类问题CpuTime ≈ StaticsDurationSyncWaitTime ≈ 0线程一直在运行属于繁忙类问题CpuTime 居中两者都有值混合问题需进一步分析Step 2: 分析CPU使用率查看 CpuFreq Usage 部分cpu0 Usage 23.5%, 1430MHZ 21.04% cpu1 Usage 23.5%, 1430MHZ 21.04% cpu2 Usage 23.5%, 1430MHZ 21.04% cpu3 Usage 23.5%, 1430MHZ 21.04%判断逻辑调用栈栈顶未阻塞CPU趋近100%考虑系统高负载类问题可忽略本次故障。Step 3: 解析采样栈增强日志会采集 多份 主线程调用栈查看 #ThreadInfos 部分#ThreadInfos Tid: 2204, Name: com.example.freeze SnapshotTime: 2021-01-01-20-05-58.292875 #00 pc 00000000000015b8 [shmm](__kernel_gettimeofday72) #01 pc 00000000001d7e44 /system/lib64/ld-musl-aarck64.so.1(clock_gettime48) #02 pc 00000000001d9f20 /system/lib64/ld-musl-aarck64.so.1(time32) #03 pc 0000000000007e2c .../libsample.so(WaitSomeTime()76) ... SubmitterStacktrace #00 pc 0000000000013108 /system/lib64/platformsdk/libuv.so(uv_queue_work292) #01 pc 0000000000008cdc .../libsample.so #02 pc 000000000005ae00 .../libace_napi.z.so(...) ...分析步骤• 统计调用路径出现次数 - 从多次采样中找到重复出现的函数调用• 抽取最大公共路径 - 识别频繁执行的代码路径• 估算耗时 - 根据采样次数估算函数累计耗时示例假设从 ThreadBlock3s 到 InputBlock 期间有6次采样• 3次采样命中 Task3 → Task3 耗时至少 900ms• 3次采样命中 Task4 → Task4 耗时至少 900msStep 4: 结合多种栈信息分析可结合以下堆栈信息一同分析堆栈类型触发条件用途ThreadBlock3S主线程卡死超过3秒定位长时间阻塞ThreadBlock6S主线程卡死超过6秒定位严重卡死AppInputBlock输入事件超时定位UI响应问题采样栈增强日志采集定位繁忙类耗时优化优先级根据调用链路出现的次数来决定优化优先级。与Android ANR日志的对比在Android开发中ANRApplication Not Responding问题定位主要依赖traces.txt文件。以下是对比分析核心机制对比对比项Android ANRHarmonyOS AppFreezedump机制系统超时后dump一次全线程栈采样周期内多次抓取调用栈栈数量通常只有0-1份瞬时栈多份采样栈时间序列CPU信息无CPU运行负载统计完整的CpuTime/SyncWaitTime统计任务溯源无SubmitterStacktrace追溯任务发起者Android ANR日志示例main tid1 Native #00 pc 0x00000000000015b8 [kernel] #01 pc 0x00000000001d7e44 libmusl.so (clock_gettime48) #02 pc 0x00000000001d9f20 libmusl.so (time32) #03 pc 0x0000000000007e2c libsample.so (WaitSomeTime76) ...问题仅能看到一个时间点的调用栈无法确认WaitSomeTime是瞬时执行还是持续阻塞。HarmonyOS 增强日志示例同样的场景增强日志提供更多信息# CPU耗时分析 CpuTime: 1500 ms - 线程实际运行了1500ms SyncWaitTime: 1500 ms - 同时等待了1500ms StaticsDuration: 3000 ms - 总统计时间3000ms# 第一次采样 (T0ms) SnapshotTime: 2021-01-01-20-05-58.292875 #00 WaitSomeTime()76 #01 process()200 #02 onInputEvent()150 # 第二次采样 (T300ms) SnapshotTime: 2021-01-01-20-05-58.592875 #00 WaitSomeTime()76 #01 process()200 #02 onInputEvent()150 # 第三次采样 (T600ms) SnapshotTime: 2021-01-01-20-05-58.892875 #00 WaitSomeTime()76 #01 process()200 #02 onInputEvent()150价值3次采样都命中WaitSomeTime证明该函数持续阻塞至少600ms。采样栈的定位效果场景1系统栈无法定位问题问题AndroidHarmonyOS增强日志主线程栈全是系统调用无法定位业务代码通过多次采样可识别耗时业务函数瞬时栈指向process无法确认具体耗时采样序列显示process累计耗时Android日志#00 [kernel] #01 EventHandler.process() #02 EventRunner.Run()只能知道在process中无法确认具体哪个子函数耗时。HarmonyOS增强日志# 采样1: process() - group_api() - render() # 采样2: process() - group_api() - render() # 采样3: process() - list_builder() - item_create()可明确group_api被多次采样命中是耗时根因。场景2繁忙类问题定位问题AndroidHarmonyOS增强日志线程Busy但不知在做什么仅有1份栈可能错过关键调用多次采样覆盖完整执行路径无法估算各函数耗时无法估算根据采样次数估算相对耗时Android日志1份栈只能看到瞬时状态。HarmonyOS增强日志采样1: Task3 - funcA - funcB (命中) 采样2: Task3 - funcA - funcC (命中) 采样3: Task4 - funcD - funcE (命中) 采样4: Task4 - funcD - funcE (命中)可确认Task3和Task4各执行2次结合总耗时可估算单次执行时间。场景3异步任务溯源问题AndroidHarmonyOS增强日志任务由谁提交无法追溯SubmitterStacktrace完整链路uv_queue_work来源无记录拼接任务提交者调用栈当采样任务来源于uv_queue_work时HarmonyOS增强日志会拼接完整的任务提交者调用栈SubmitterStacktrace #00 uv_queue_work292 #01 libsample.so #02 ArkNativeFunctionCallBack() #03 RTStub_PushCallArgsAndDispatchNative() #04 BCStub_HandleCallthis0Imm8V8StwCopy372 #05 at Index.ts:381:36 - 追溯到具体JS代码行总结对比场景Android ANRHarmonyOS AppFreeze阻塞类等锁/IO3s/6s栈可定位同样可定位系统栈占比高难以穿透采样栈可穿透瞬时栈指向模糊无法确认耗时采样序列可确认繁忙类频繁执行仅1份栈难以分析多次采样轻松定位异步任务溯源无法追溯SubmitterStacktrace可追溯核心优势HarmonyOS增强日志的采样栈机制将瞬时切面转化为时间序列特别适合Android难以定位的繁忙类和系统栈密集类问题。如下图可以完整的看出调用序列中的瓶颈在appfreeze_threadblock模拟函数中。总结冻屏增强日志的核心价值在于将瞬时切面转化为时间序列让开发者能够追踪主线程在一段时间内的完整执行轨迹从而精准定位繁忙类冻屏的根因。增强日志使用口诀• 先看CpuTime - 判断是阻塞还是繁忙• 再看Cpu使用率 - 确认是否为调度问题• 后解析采样栈 - 找出耗时函数• 结合多栈分析 - 确定优化优先级