Android应用卡顿监控方案原理和对比_android jankstats


其中**CALLBACK\_ANIMATION**是处理动画相关的逻辑,而**CALLBACK\_TRAVERSAL**则会调用到ViewRootImpl的**performTraversals()** 函数,从而执行到我们所熟悉的View的measure、layout、draw三大流程。


所以可以说,**doFrame()** 函数包含了应用层绘制一帧的逻辑处理。


![](https://img-blog.csdnimg.cn/img_convert/106672636880dcdb4947d4210d0fa1b8.webp?x-oss-process=image/format,png)


由于Choreographer处于如此重要的一个位置,基本上所有的卡顿监控都会围绕着Choreographer进行的,除了自带的掉帧计算,Choreographer 提供的 FrameCallback 和 FrameInfo都是应用层可以直接访问的接口。


下面介绍一下市面上开源方案的几种实现方式和简单对比。


### 1 Choreographer的FrameCallback


**TinyDancer** 就是通过这种方式计算出FPS。 核心代码:



Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {
override fun doFrame(frameTimeNanos: Long) {
if (lastFrameTimeNanos > 0) {
val frameTime = (frameTimeNanos - lastFrameTimeNanos) / NANOS_PER_MS
}
lastFrameTimeNanos = frameTimeNanos
Choreographer.getInstance().postFrameCallback(this)
}

})


通过记录doFrame回调的间隔时间作为每帧耗时frameTime,如此也很容易计算出FPS=1000/frameTime,掉帧数=frameTime/16.6。


### 2 Choreographer + Looper


Tencent/**matrix** 虽然也是基于Choreographer,但其监测FPS的机制和上面的FrameCallback方案不太一样。 由前面Choreographer的介绍可知,所谓每一帧其实指的就是input、animation、traversal三种事件对应的三个doCallback方法的执行结果,而matrix统计帧耗时就是通过监测这三个方法的执行总时间来表示。matrix监测FPS的主要实现在`LooperMonitor`和`UIThreadMoniter`两个类里。


1. `LooperMonitor`为主线程Looper设置一个Printer来监听UI线程每个Message的开始、结束,从而得到Message的执行耗时。(方案同 **BlockCanary** )



class LooperPrinter implements Printer {
@Override
public void println(String x) {

dispatch(x.charAt(0) == ‘>’, x);
}

private void dispatch(boolean isBegin, String log) {
    for (LooperDispatchListener listener : listeners) {
        if (isBegin) {
            listener.onDispatchStart(log);
        } else {
            listener.onDispatchEnd(log);
        }
     }
}

}


2. `UIThreadMoniter`通过java反射向Choreographer的CALLBACK\_INPUT、CALLBACK\_ANIMATION、CALLBACK\_TRAVERSAL三个事件的callback队列的**头部**插入自定义callback。



    //UIThreadMonitor.java
    @Override
    public void run() {
   
   
        doFrameBegin(token);
        doQueueBegin(CALLBACK_I
2025-07-18 09:37:24.226 1425-1425 vendor.qti...al-service ven...qti.hardware.perf-hal-service E ExtendedPerfBoost: extended_perfboost_verification() 738: Ok, set boost params. hintid=4225 hinttype=1 prio=3, clientpid=2569 packagename=com.example.text params=boost:1 cpu0:1804800 cpu4:2496000 cpu7:2592000 cpumask:ff 2025-07-18 09:37:24.248 20986-20986 Zygote usap64 E process_name_ptr:20986 com.example.text 2025-07-18 09:37:24.319 27603-3228 SuggestManager com.miui.securitycenter.remote E openApp name = com.example.text 2025-07-18 09:37:24.327 4285-5371 ActivityManagerWrapper com.miui.home E getRecentTasks: mainTaskId=10282 userId=0 windowMode=1 baseIntent=Intent { act=android.intent.action.MAIN flag=268435456 cmp=ComponentInfo{com.example.text/com.example.text.MainActivity} } 2025-07-18 09:37:24.335 27603-13357 AntiFraud com.miui.securitycenter.remote E hookDetectUnsafeAppStart error, android.content.pm.PackageManager$NameNotFoundException: com.example.text at android.app.ApplicationPackageManager.getApplicationInfoAsUser(ApplicationPackageManager.java:515) at android.app.ApplicationPackageManager.getApplicationInfo(ApplicationPackageManager.java:498) at android.app.ApplicationPackageManager.getApplicationInfo(ApplicationPackageManager.java:492) at w2.b.f(Unknown Source:12) at w2.b$c.onForegroundInfoChanged(Unknown Source:21) at com.miui.gamebooster.mutiwindow.b$a.onForegroundInfoChanged(Unknown Source:152) at miui.process.IForegroundInfoListener$Stub.onTransact(IForegroundInfoListener.java:86) at android.os.Binder.execTransactInternal(Binder.java:1351) at android.os.Binder.execTransact(Binder.java:1282) 2025-07-18 09:37:24.337 8279-10833 SuggestManager com.miui.securitycenter.remote E openApp name = com.example.text ---------------------------- PROCESS STARTED (20986) for package com.example.text ----------------------------
最新发布
07-19
<think>我们正在分析Android系统日志,特别是与性能提升(ExtendedPerfBoost)、CPU频率调整以及应用启动异常(com.example.text)相关的问题。 步骤: 1. 获取系统日志:使用adb logcat命令捕获日志,可以添加过滤条件以缩小范围。 2. 分析日志中的关键事件:查找与ExtendedPerfBoost、CPU频率调整(可能涉及cpufreq、thermal等关键词)以及应用启动(ActivityManager)相关的错误或警告。 3. 定位问题:结合时间戳,分析这些事件之间的关系,判断是否是性能调整导致了应用启动异常。 具体操作: 一、获取日志 建议使用以下命令捕获日志(按需调整过滤条件): ```bash adb logcat -v time -b all | grep -E "ExtendedPerfBoost|cpufreq|thermal|ActivityManager|com.example.text" ``` 或者保存到文件再分析: ```bash adb logcat -v time > logcat.txt ``` 二、分析日志中的关键信息 1. **ExtendedPerfBoost相关**: - 查找日志中关于ExtendedPerfBoost的条目,注意其状态(申请、释放、失败等)。 - 例如,可能出现申请超时、被拒绝等错误。 2. **CPU频率调整**: - 关注cpufreq相关的日志,查看CPU频率的变化情况,是否因为温度限制(thermal)或其他原因导致降频。 - 注意:系统可能会因为温度过高、电量不足等原因限制CPU频率。 3. **应用启动异常**: - 查找com.example.text应用的启动记录(ActivityManager: Displayed com.example.text/.MainActivity)。 - 注意启动时间是否过长,以及是否有ANR(Application Not Responding)或崩溃信息。 三、常见错误模式及解决方法 1. **场景1:ExtendedPerfBoost申请失败导致应用启动慢** - 日志特征:在应用启动期间,有申请ExtendedPerfBoost的记录,但返回失败。 - 可能原因:系统资源紧张(如其他进程正在占用高性能模式)、系统策略限制等。 - 解决:检查系统性能服务状态,确认是否有其他进程长时间占用高性能模式。 2. **场景2:因温度过高导致CPU降频** - 日志特征:出现thermal相关的日志,显示温度过高,随后cpufreq日志显示频率下降。 - 可能影响:应用启动时CPU频率被限制,导致启动缓慢。 - 解决:优化应用启动过程,减少CPU密集型操作;或者改善设备散热。 3. **场景3:应用自身启动问题** - 日志特征:ActivityManager显示应用启动超时(ANR),同时可能伴有应用内部错误(如主线程阻塞、死锁等)。 - 解决:分析应用自身代码,优化启动流程。 四、日志分析示例 假设我们有一段日志: ``` 08-01 10:00:00.000 I/ExtendedPerfBoost( 123): acquire boost for com.example.text, duration=3000 08-01 10:00:00.100 E/ExtendedPerfBoost( 123): acquire failed for com.example.text, reason: RESOURCE_BUSY 08-01 10:00:03.000 I/ActivityManager( 456): Displayed com.example.text/.MainActivity: +3s500ms ``` 分析: - 应用启动时申请了ExtendedPerfBoost,但失败了(RESOURCE_BUSY)。 - 启动时间达到了3.5秒,明显过长。 - 可能原因:性能提升申请失败导致应用启动时无法获得足够的CPU资源。 五、进一步诊断工具 1. **systrace**:用于分析应用启动过程中的CPU调度、锁等待等问题。 ```bash python systrace.py -b 32768 -t 5 -o mytrace.html sched freq idle am wm gfx view binder_driver ``` 然后启动应用,停止抓取。在生成的mytrace.html中查看应用启动过程。 2. **dumpsys cpuinfo**:查看CPU使用情况。 ```bash adb shell dumpsys cpuinfo ``` 3. **top命令**:实时查看CPU占用。 ```bash adb shell top -m 10 -d 1 ``` 六、解决方案建议 - 如果问题在ExtendedPerfBoost申请失败,可以尝试延迟申请或重试机制(但需注意系统限制)。 - 优化应用启动流程,减少对性能提升的依赖,例如通过异步初始化、延迟加载等。 - 检查系统层是否有过度限制性能的策略,适当调整(需系统权限)。 七、相关问题 §§相关问题§§ 1. 如何解读systrace报告中关于CPU频率调度信息? 2. 应用启动优化有哪些常用方法? 3. Android系统如何管理多个进程同时申请性能提升(如ExtendedPerfBoost)?</think>### Android系统日志分析:ExtendedPerfBoost、CPU调整与应用启动异常 #### 一、核心日志分析路径 1. **日志采集指令** 使用过滤命令获取关键日志: ```bash adb logcat -v time | grep -E "ExtendedPerfBoost|cpufreq|ActivityManager|com.example.text" ``` 建议保存完整日志: ```bash adb logcat -v time > full_log.txt ``` 2. **关键日志标记解析** | 日志关键词 | 含义说明 | 典型问题表现 | |---------------------|--------------------------------------------------------------------------|---------------------------------------| | `ExtendedPerfBoost` | 系统性能提升服务,用于临时提升CPU/GPU频率[^1] | `Boost acquire failed`(申请失败) | | `cpufreq` | CPU调频子系统日志 | `Frequency limited by thermal`(降频)| | `ActivityManager` | 应用生命周期管理 | `ANR in com.example.text`(无响应) | | `Binder` | 跨进程通信机制 | `transaction too large`(通信超限) | #### 二、典型异常场景分析 1. **ExtendedPerfBoost申请失败** ```log 08-01 10:05:23.521 E/ExtendedPerfBoost: Acquire failed for com.example.text (reqId=5), reason: RESOURCE_BUSY ``` **原因**: - 系统资源被更高优先级进程占用(如系统服务) - 设备温度过高触发限流保护(结合`thermal-engine`日志) **解决方案**: - 延迟启动耗时任务:`postDelayed()`避开启动峰值 - 检查是否过度申请:`isBoostSupported()`判断可用性[^2] 2. **CPU频率异常调整** ```log 08-01 10:05:24.115 W/msm-cpufreq: CPU0 frequency capped to 1478MHz (thermal limit) ``` **影响**: - 应用启动时间延长(通常>3秒触发ANR) - 界面渲染卡顿(`Choreographer`跳帧警告) **优化策略**: ```kotlin // 在Application中初始化轻量级组件 class MyApp : Application() { override fun onCreate() { super.onCreate() CoroutineScope(Dispatchers.IO).launch { initLightweightComponents() // 避免主线程阻塞 } } } ``` 3. **应用启动异常定位** ```log 08-01 10:05:25.742 E/ActivityManager: ANR in com.example.text, Reason: Broadcast of Intent { act=android.intent.action.SCREEN_ON } ``` **分析步骤**: 1. 检查`/data/anr/traces.txt`获取堆栈信息 2. 使用`systrace`分析启动过程: ```bash python systrace.py -a com.example.text -b 16384 -o trace.html sched freq ``` 3. 重点关注锁竞争:`monitor contention`日志项 #### 三、性能优化实施建议 1. **CPU调频策略优化** 通过cgroup限制后台进程资源: ```bash # 限制后台进程CPU配额 echo "background 50" > /dev/cpuctl/bg_non_interactive/cpu.shares ``` 2. **启动时间优化公式** 总启动时间可拆解为: $$ T_{total} = T_{init} + T_{io} + T_{cpu} + T_{render} $$ - $T_{init}$:类加载耗时(优化Dex加载) - $T_{io}$:文件读写耗时(启用`StrictMode`检测) - $T_{cpu}$:计算耗时(使用基准测试工具[JankStats]) 3. **ExtendedPerfBoost最佳实践** ```java // 正确申请性能提升 if (PerfBoostManager.isSupported()) { PerfBoost boost = new PerfBoost.Builder() .setDuration(2000) // 精确控制时长 .setScenario(SCENARIO_APP_LAUNCH) .build(); boost.acquire(); // 需在UI线程操作 } ``` #### 四、辅助诊断工具推荐 | 工具名称 | 用途描述 | 关键命令/参数 | |-------------------|-----------------------------------|----------------------------------| | **Battery Historian** | 分析能耗与CPU关系 | `adb bugreport > bugreport.zip` | | **Perfetto** | 系统级性能跟踪 | `record_android_trace -o trace_file` | | **Debug API** | 实时监控CPU频率 | `adb shell dumpsys cpuinfo` | > **注**:Android 12+ 对后台进程的CPU限制更严格,需特别关注`BackgroundRestriction`日志项[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值