第一章:性能监控基础

各位同学,咱们今天正式开课。

做Android性能优化,说白了就是跟手机里的资源打交道。CPU、内存、IO、网络,这些家伙就像四个脾气各异的同事——有的急性子,有的爱偷懒,有的动不动就卡住。你得先摸清他们的底细,才能管好他们。

我个人习惯,每次接手一个新项目,第一件事不是写代码,而是先把系统架构图摊开看一遍。为什么?因为你不了解系统怎么工作,就根本不知道性能问题出在哪。

1.1 Android系统架构概览

Android系统从下往上,大致分这么几层:

  • Linux内核层:这是地基。进程管理、内存管理、网络协议栈、驱动,全在这。你想想看,没有内核,你的App连个线程都跑不起来。
  • 硬件抽象层(HAL):把硬件厂商的驱动封装成统一接口。嗯,这里要注意,不同厂商的HAL实现差异很大,我遇到过某款手机因为HAL层的内存泄漏,导致整个系统越来越卡。
  • 系统运行时层(ART & Native库):ART负责把Java字节码编译成机器码,Native库处理图形、音频、数据库等底层操作。说白了,你的App跑得快不快,一半看ART的编译策略。
  • Java框架层:ActivityManager、WindowManager、PackageManager……这些Manager就是系统的大管家。你调一个startActivity,背后要经过多少层调用?我数过,至少七八个关键节点。
  • 应用层:你的App就在这。但别以为应用层只关心业务逻辑——你写的每一行代码,最终都会映射到下面几层的资源消耗上。

我曾经在优化一个视频App时,发现滑动列表卡顿。查了半天,问题出在应用层频繁调用Binder通信,导致内核层的binder线程池爆满。你看,问题往往不在你眼前那层。

1.2 性能指标定义

性能优化不能靠感觉。你得有数据,有指标。我见过太多人一上来就说「这App好卡」,但问他「卡在哪?CPU还是IO?」他就答不上来了。

CPU指标

  • CPU使用率:分用户态、内核态、总使用率。用户态高说明你的业务逻辑在跑,内核态高说明系统调用频繁。我有个经验:如果内核态占比超过30%,大概率是IO或锁竞争出了问题。
  • 负载(Load Average):1分钟、5分钟、15分钟的平均负载。这个值超过CPU核心数时,说明系统在排队了。你想想看,排队等CPU,App能不卡吗?
  • 线程数:线程不是越多越好。我见过一个App开了200多个线程,结果大部分都在等锁。说白了,线程切换的开销比干活还大。

内存指标

  • PSS(比例集大小):这是Android里最实在的内存指标。它把共享库按比例分摊到每个进程。我建议你看内存时,优先看PSS,别只看RSS。
  • GC次数与停顿时间:ART的GC虽然比Dalvik强,但频繁GC还是会卡。我曾经优化过一个App,GC停顿占了总时间的15%,优化后降到了2%。
  • 内存碎片:这个指标比较隐蔽。系统内存碎片化严重时,即使总内存够用,也可能分配不出大块连续内存。嗯,这里要注意,低内存设备上这个问题尤其突出。

IO指标

  • IO等待时间:CPU在等IO完成的时间占比。这个值高了,说明磁盘是瓶颈。我遇到过一款手机,IO等待时间占了30%,换了个UFS 3.0的存储后直接降到5%。
  • 读写速率:顺序读写和随机读写差别很大。数据库操作大多是随机读写,所以别只看顺序读写的速度。
  • 文件描述符数:每个进程能打开的文件数有限。我见过一个App因为没关文件流,导致fd耗尽,整个App直接崩溃。

网络指标

  • 延迟(Latency):从发请求到收到响应的总时间。包括DNS解析、TCP握手、TLS协商、数据传输。我建议你关注「首字节时间」,这个指标最能反映网络质量。
  • 吞吐量(Throughput):单位时间内传输的数据量。别只看带宽,实际吞吐量受限于网络拥塞、丢包率等因素。
  • 丢包率:这个指标很关键。丢包1%可能感觉不明显,但丢包5%以上,TCP的拥塞控制会让你感觉网络像蜗牛。

核心原则:性能指标不是孤立看的。CPU高不一定有问题,但如果CPU高同时IO等待也高,那大概率是IO瓶颈导致CPU空转。我习惯把四个指标放在一张图上对比,一眼就能看出瓶颈在哪。

1.3 监控工具链介绍

工具是工程师的第三只手。我这些年用过的工具不下二十种,但真正好用的就那么几个。下面是我个人推荐的「黄金组合」。

工具 监控维度 适用场景
systrace / Perfetto CPU、线程、系统调用 分析卡顿、启动慢、ANR
dumpsys meminfo 内存PSS、GC、堆信息 内存泄漏、OOM排查
strace 系统调用、IO操作 IO瓶颈、文件操作异常
tcpdump / Wireshark 网络包、延迟、丢包 网络请求慢、连接异常
SimplePerf CPU采样、热点函数 定位CPU热点、优化算法

我重点说说Perfetto。这工具是Google亲儿子,比systrace强太多了。它不仅能看CPU调度,还能看内存分配、IO操作、网络事件。你想想看,一条时间线上把所有事件都串起来,问题定位效率翻倍。

我的小技巧:用Perfetto时,记得开启「long trace」模式。默认的trace时间太短,很多偶发问题抓不到。我一般设成30秒,足够复现大部分问题了。

还有一个工具容易被忽略——dumpsys。这命令能查系统服务的内部状态。比如dumpsys activity可以看Activity栈,dumpsys window可以看窗口层级。我曾经用dumpsys meminfo抓到一个第三方SDK的内存泄漏,那个SDK在后台偷偷缓存图片,占了200多MB。

避坑指南:我曾经在线上环境直接跑systrace,结果trace文件太大,把/data分区撑爆了,导致系统重启。后来我学乖了——线上环境用轻量级的采样工具,比如SimplePerf的采样模式,或者用自定义的指标采集器。全量trace只用在测试机或预发布环境。

最后说一句:工具只是手段,不是目的。你拿着Perfetto的火焰图,看不懂CPU调度策略,那也白搭。所以下一章,我会带大家深入CPU调度原理,看看系统到底是怎么分配时间片的。

好,第一章就到这里。记住:性能监控不是一次性的工作,而是贯穿整个开发周期的习惯。你每天花10分钟看看指标,能省下后面几天的排查时间。