Fork me on GitHub
侧边栏

Perfetto Systrace不同CPU运行状态异常原因 - Running长

序言

本文针对使用Perfetto/Systrace分析不同操作任务的CPU执行状态时常见的异常原因进行了汇总,对实战中的问题分析可起到抛砖引玉的作用。以下异常情况都来自实际的案例分析,因此非常具有参考价值,各球友如果遇到过其他没提及过的案例时可在下面直接回复。

Android线程被分为16种状态:

  • Debug
  • Exit Dead
  • Runnable
  • Running
  • Sleeping
  • Stopped
  • Task Dead
  • Uninterruptible Sleep
  • Uninterruptible Sleep WakeKill
  • Uninterruptible Sleep |Waking
  • Uninterruptible Sleep Block I/O
  • Uninterruptible Sleep WakeKill Block I/O
  • Uninterruptible Sleep Waking Block I/O
  • Wakekill
  • Waking
  • Zombie

出处:trace-viewer/trace_viewer/model/thread_time_slice.html - platform/external/chromium-trace - Git at Google

其中最为关键的是Running、Runnable、Uninterruptible Sleep(或称为D状态)以及Sleep状态。 这四个状态直接影响到了一个操作的执行性能,因此讨论也由此展开;

Running 时间长显示方式

Trace中显示绿色,表示线程处于运行态

image

原因1:代码本身复杂度高,执行耗时久

这是最常见的一种方式;

优化建议:优化逻辑、算法,降低复杂度。为了进一步判断具体是哪个函数耗时,可使用AS CPU Profiler、simpleperf,或者自己通过Trace.begin/end() API添加更多 tracepoint点。

原因2:代码以解释方式执行

Trace中看到[Compiling]字眼时可能意味着它是解释执行方式进行。刚安装的应用(未做odex)的程序经常会出现这种情况。

优化建议:使用dex2oat之后的版本试试,解释执行方式下的低性能暂无改善方法,除非执行dex2oat或者提高代码效率本身。

除此之外,使用了编程语言的某种特性,如频繁的调用JNI,反复性反射调用。除了通过积攒经验方式之外,通过工具解决的方法就是通过 CPUProfiler、simpleperf 等工具进行诊断。

原因3:线程跑小核,导致执行时间长

对CPU Bound的操作来说跑在小核可能没法满足性能需求,因为小核的定位是处理非UX强相关的线程。不过Android 没办法保证这一点,有时候任务就是会安排在小核上执行。

优化建议:线程绑核、SchedBoost等操作,让线程跑尽量跑更高算力的核上,比如大核。有时候即使迁核了也不见效,这时候要看看频率是否拉得足够高,见“原因4”。

原因4:线程所跑的大核运行频率太低

优化建议:

  1. 优化代码逻辑主动降低运行负载

  2. 修改调度器升频相关的参数,让CPU根据负载提频更激进3.用平台提供的接口锁定CPU频率(俗称的「锁频」)

原因5:温升导致CPU关核、限频优化建议:

手机因结构原因导致散热能力差或温升参数过于激进时,为了保护体验跟不烫伤人,几乎所有手机厂家的系统会限制CPU频率或者直接关核。排查思路是首先需要找到触发温升的原因。

温升的排查的第一步,首先要看是外因导致还是内因导致。外因是指是否由外部高温导致,如太阳底下,火炉边;往往夏天的时候导致手机发热的情况约严重。

内因主要由CPU、Modem、相机模组或者其他发热比较厉害的器件导致的。以CPU为例,如果后台某个线程吃满CPU,那就首先要解决它。如果是前台应用负载高导致大电流消耗,同样道理,那就降低前台本身的负载。其他器件也是同样道理,首先要看是否是无意义的运行,其次是优化业务逻辑本身。

除此之外,温升参数过于激进的话导致触发限频关核的概率也会提高,因此通过与竞品对比等方式调优温升参数本身来达到优化目的。

原因6:CPU算力弱

优化建议:

ARM处理器在相同频率下不同微架构的配置导致的性能差异是非常明显的,不同运行频率、L1/L2Cache的容量均能影响CPU的MIPS(Million Instructions Per Second)执行结果。

优化思路有两条:

  1. 编译器参数
  2. 优化代码逻辑

第一条比较难,大部分应用开发者来说也不太现实,系统厂商如华为,方舟编译器优化JNI的思路本质是不改应用代码情况下提高代码执行效率来达到性能上的提升。

第二条可以通过simpleperf等工具,找到热点代码或者观察CPU行为后做进一步的改善,如:Cache miss 率过高导致执行耗时,就要优化内存访问相关逻辑。

代码复杂指令过多导致耗时,就要优化代码逻辑,降低代码复杂度。

设计好业务缓存,尽量提高缓存命中率,避免抖动(反复行的申请与释放)

Perfetto 状态 内核 task->state 说明
running TASK_RUNNING 正在 CPU 上执行
runnable TASK_RUNNING 已经 runnable,可能在 runqueue 上等待调度
sleeping TASK_INTERRUPTIBLE / TASK_UNINTERRUPTIBLE 不可运行,阻塞状态
posted @ 2025-05-08 16:33  yooooooo  阅读(263)  评论(0)    收藏  举报