耗电-CPU与后台优化

CPU是App最容易"无意识"耗电的模块,而后台则是最容易"偷偷"耗电的场景。本文聚焦这两大问题域,给出具体的优化手段。 一、CPU耗电的根本原因 根据 耗电-原理 中的分析,CPU耗电由三部分构成: 活跃时间:CPU处于C0/P0的时间。 瞬时功率:和P-State频率相关。 唤醒次数:频繁从C-State唤醒无法进入深度休眠。 对应三条优化方向: 优化方向 策略 减少活跃 任务及时结束,该停就停 降低功率 避免无谓的满核满频,使用合适的QoS 合并唤醒 聚合Timer、聚合任务,让CPU能连续工作后进入深休眠 二、识别CPU耗电热点 从MetricKit入手 cumulativeCPUTime 是线上最直接的CPU指标。对比同版本前后、同机型前后的CPU时长,能快速定位回归。 Time Profiler的使用技巧 在Instruments中抓一份Time Profiler Trace后: 按"Heavy Stack"视图查看耗时函数。 关注后台的采样(通过Xcode的生命周期切换复现)。 查看线程调用频率——单次耗时低但高频调用的函数,同样是耗电大头。 代码层面的CPU异味 // 1. 死循环轮询 while isWaitingForData { if dataReady { break } } // 2. 主线程sleep循环 DispatchQueue.global().async { while true { checkStatus() Thread.sleep(forTimeInterval: 0.1) } } // 3. 密集Timer Timer.scheduledTimer(withTimeInterval: 0.016, repeats: true) { _ in self.updateUI() } // 4. 无限制的CADisplayLink displayLink = CADisplayLink(target: self, selector: #selector(tick)) displayLink.add(to: .main, forMode: .common) // 页面隐藏后忘记invalidate 这些代码在Time Profiler中都会显示出异常高的调用频率。 ...

May 2, 2026

耗电-原理

本文从硬件功耗模型、iOS系统的能效调度机制、以及各个硬件模块的功耗特性三个维度,系统性地讲解iOS App耗电的底层原理。 功耗的基本概念 功率、能量与电量 功率(Power):单位时间内消耗的能量,单位为瓦特(W)。 能量(Energy):功率在时间上的积分,单位为焦耳(J)或毫瓦时(mWh)。 电量(Battery Capacity):电池能存储的总能量,单位为毫安时(mAh)。 \[ Energy = \int P(t)\,dt \]对于一段时间内近似恒定的功率,可以简化为 \( E = P \times t \)。这也是所有耗电优化的起点——要么降功率(P),要么降时间(t)。 电池电压与电流 iPhone使用锂电池,标称电压约为3.7~3.8V。操作系统看到的电流则随着硬件负载实时变化。可以近似认为: \[ P(t) = V \times I(t) \]在App层面,我们无法直接测量V和I,但可以通过 UIDevice.current.batteryLevel 观察电量百分比,通过 IOKit 私有API读取更精细的电池状态(后面检测篇会详细讲)。 硬件功耗特性 不同硬件模块的功耗曲线差异非常大。理解每个模块的特性,才能找到最有效的优化点。 CPU:P-State与C-State 现代CPU(包括Apple Silicon)通过 动态电压频率调整(DVFS) 来平衡性能与功耗。 P-State(Performance State) P-State描述CPU在工作时的电压/频率档位。以Apple A系列芯片为例,大核和小核都有多个P-State: flowchart LR subgraph P-State P0["P0最高频率功耗最大"] P1["P1中高频率"] P2["P2中低频率"] P3["P3低频率功耗小"] end P0 -.->|负载下降| P1 P1 -.-> P2 P2 -.-> P3 P3 -.->|负载上升| P0 CPU的功耗与频率大致呈 立方关系(电压随频率升高,功耗 ≈ V² × f ≈ f³)。这意味着: ...

May 2, 2026

耗电-定位与传感器优化

定位是iOS设备上公认的"耗电大户",GPS冷启动一次动辄十几秒的高功耗;传感器(加速度计、陀螺仪等)虽然单次功耗不高,但高频采样会累积成可观的电量消耗;屏幕则是 持续 耗电的模块,其功耗和亮度、刷新率、像素颜色都强相关。本文聚焦这三类问题,给出工程化的优化方案。 一、定位精度与功耗的关系 iOS通过 CLLocationManager 提供定位服务,底层融合了 GPS、蜂窝基站、WiFi、蓝牙信标 等多源信号。精度越高,需要开启的硬件越多,功耗越高。 精度常量 精度范围 硬件使用 典型功耗 kCLLocationAccuracyBestForNavigation <5m GPS + 传感器融合(需插电) 极高 kCLLocationAccuracyBest ~10m GPS持续 高 kCLLocationAccuracyNearestTenMeters ~10m GPS + WiFi 高 kCLLocationAccuracyHundredMeters ~100m WiFi + 基站 中 kCLLocationAccuracyKilometer ~1km WiFi + 基站(低频) 低 kCLLocationAccuracyThreeKilometers ~3km 基站 极低 注:iOS 14+ 引入的 ReducedAccuracy 是用户授权层面的"粗略位置",通过 CLAccuracyAuthorization.reducedAccuracy 体现,而不是 desiredAccuracy 常量。即使 App 申请了高精度,只要用户选择了"粗略位置",系统就只会返回约5公里精度的数据,功耗也随之降到极低。 不同业务场景的精度选择 业务 推荐精度 导航 BestForNavigation(仅使用中 + 插电时) 打车、骑行记录 Best 外卖、附近的人 HundredMeters 天气、资讯推荐 Kilometer 或 ThreeKilometers 反欺诈、粗粒度风控 ReducedAccuracy(尊重隐私 + 省电) 常见反例 // Bad: 所有场景都用Best,页面打开就开,关闭不关 locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.startUpdatingLocation() // Bad: distanceFilter用kCLDistanceFilterNone,每次都回调 locationManager.distanceFilter = kCLDistanceFilterNone 正确姿势:按需精度 + 距离过滤 class WeatherLocationClient: NSObject, CLLocationManagerDelegate { private let manager = CLLocationManager() private var completion: ((CLLocation) -> Void)? override init() { super.init() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyKilometer manager.distanceFilter = 500 // 500米才更新 } func requestOnce(_ completion: @escaping (CLLocation) -> Void) { self.completion = completion manager.requestLocation() // 一次性定位,完成后自动停止 } func locationManager(_ manager: CLLocationManager, didUpdateLocations locs: [CLLocation]) { guard let loc = locs.last else { return } completion?(loc) completion = nil } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { completion = nil } } requestLocation()(iOS 9+)是最省电的一次性定位入口,系统会在获取到满足精度的定位后自动停止硬件。 ...

May 2, 2026

耗电-检测

本文介绍iOS耗电问题的检测手段,从开发阶段的本地工具,到线上的监控体系,帮助团队形成一套完整的耗电可观测能力。 检测手段全景 flowchart TB subgraph Dev["研发阶段"] EG["Xcode Energy Gauge实时能效评分"] Inst["InstrumentsEnergy Log / Time Profiler"] XCT["XCTest能效测试"] end subgraph Test["测试阶段"] Thermal["热节流测试"] Battery["真机电量消耗测试"] IOKit["IOKit内部分析"] LPM["低电量模式回归"] end subgraph Online["线上阶段"] MK["MetricKit"] Self["自建实时采集电量 / CPU / Thermal / 生命周期"] Report["埋点上报数据看板"] end Dev --> Test --> Online 一、Xcode Energy Gauge Xcode在真机调试时,“Debug Navigator → Energy Impact"提供了实时能效评估。 能效评分(Energy Impact) Xcode将功耗分为5档: 等级 含义 典型值 Very Low / Low 正常使用 03 / 48 High 偏高,需要关注 9~16 Very High 严重,必须优化 17~20 评分由以下几个因素构成: CPU:平均CPU使用率。 Network:网络活跃时间与流量。 Location:定位活跃时间与精度。 GPU:GPU活跃时间。 Background:后台活跃时间。 Overhead:系统唤醒代价。 典型使用流程 Xcode连接真机(模拟器的数据不准确)。 运行App,选择Debug Navigator → Energy Impact。 进行典型操作(刷Feed、看视频、聊天等),观察评分。 如果出现High/Very High,使用Instruments进一步定位。 二、Instruments Energy Log Instruments中有多个和能效相关的工具: ...

May 8, 2026

耗电-治理

前面几篇分别讲了耗电的原理、检测、以及CPU/网络/定位/屏幕的具体优化手段。本文把这些内容整合起来,给出一套面向工程团队的 耗电治理体系:从研发规范、线上监控、问题排查到常态化运营。 耗电治理是 APM 资源子系的一部分,与稳定性、流畅性、启动指标共用同一套监控与告警基础设施。完整的 APM 建设方案见 APM 系列:数据采集、B端平台设计。 一、治理体系全景 一个成熟的iOS耗电治理体系通常由四个闭环组成: flowchart TB subgraph Dev["研发侧"] R1["能效规范"] R2["架构层能效约束"] R3["Code Review清单"] end subgraph Test["测试侧"] T1["XCTest能效基线"] T2["真机续航测试"] T3["极端场景矩阵"] end subgraph Online["线上侧"] O1["MetricKit接入"] O2["自建CPU/电量采样"] O3["场景化埋点"] O4["大盘 + 告警"] end subgraph Gov["运营侧"] G1["版本耗电报告"] G2["Top问题跟进"] G3["复盘与规范迭代"] end Dev --> Test --> Online --> Gov --> Dev 二、研发阶段的能效规范 模块准入清单 每个新增模块在接入主App前,必须回答以下问题: 维度 问题 CPU 是否有常驻Timer?是否有轮询?是否在不可见时暂停? 网络 请求频率?是否合并?是否支持后台取消? 定位 是否申请定位?精度多少?后台策略? 传感器 是否开启传感器?采样率?视图生命周期? 后台能力 是否申请Background Mode?如何收敛? 动画/渲染 是否有长驻动画?是否适配ProMotion? Low Power 低电量模式下的降级策略? 权限 涉及的用户权限?是否遵守最小权限原则? 架构层面的能效约束 一些通用能力可以在架构层统一管控,避免各业务重复踩坑: ...

May 7, 2026

耗电-网络优化

网络是iOS设备上仅次于屏幕的耗电大户。和其他模块不同,网络耗电的"坑"非常隐蔽——请求本身只持续几十毫秒,但无线电(Radio)会有10~20秒的"尾能耗"。本文从无线电能效模型出发,给出具体的网络优化手段。 一、无线电能效模型回顾 RRC状态机再看一眼 无线电不是"开就费电、关就不费电"这么简单。它在连接和空闲之间存在中间状态: stateDiagram-v2 [*] --> Idle: 初始/长时间空闲 Idle --> Connected: 发送/接收 Connected --> ShortDRX: 空闲~1秒 ShortDRX --> LongDRX: 空闲~5秒 LongDRX --> Idle: 空闲~10秒 Connected --> Connected: 持续通信 ShortDRX --> Connected: 新请求 LongDRX --> Connected: 新请求 状态 功耗 说明 Connected 最高(12W) 数据传输中 Short DRX 中等 周期性监听页 paging,仍持有连接 Long DRX 低 周期变长,仍在空中接口 Idle 极低(~几mW) 完全释放 一次请求从发起到彻底回到Idle大约 12~20秒。这个尾巴就是"Tail Energy"。 能效启示 10次请求,每次间隔2秒: - Radio持续处于Connected/DRX状态 ≈ 30秒 - 实际传输时间可能只有几百ms 10次请求合并成1次: - Radio活跃时间 ≈ 15秒(主要是尾巴) - 节省约50%~70%的Radio能耗 结论:网络能效的核心就是"减少Radio醒来的次数"。 ...

May 2, 2026

耗电

耗电(Energy Consumption)是移动应用质量的重要指标之一。一款耗电过快的App会直接影响用户的续航体验,轻则被用户吐槽,重则被系统标记为"耗电大户"(在iOS的"设置 → 电池"中显示),最终被用户卸载。 本系列文章从iOS功耗模型入手,系统性地介绍耗电问题的原理、检测、优化与治理。 为什么要关注耗电 iOS设备的电池容量有限(iPhone通常在3000~5000mAh),而应用的功耗会直接影响续航时间。苹果在iOS 8之后提供了"电池用量"统计入口,用户可以清楚地看到每个App消耗的电量比例。 常见的耗电投诉场景: 场景 用户感知 典型原因 后台待机一晚电量掉20% 手机放着不用也掉电 后台定位、后台音频、后台Fetch未合理释放 App使用1小时电量掉30% 使用过程电量下降过快 CPU长时间高占用、高频网络请求、GPU密集渲染 手机发烫 设备温度异常升高 CPU/GPU长期满载、持续定位、频繁屏幕唤醒 被系统标记为"后台活动"过高 系统提示"此App正在消耗大量电池" 后台任务未合理调度,违反能效规则 苹果对"耗电"非常敏感——从iOS 9开始引入低电量模式(Low Power Mode),从iOS 13开始加强后台任务的能效审查(BackgroundTasks框架),从iOS 15开始通过MetricKit将功耗数据开放给开发者。 iOS功耗模型概述 iOS设备的功耗来源可以分为以下几大类: flowchart TB Battery["电池总功耗"] Battery --> CPU["CPU计算、编解码"] Battery --> GPU["GPU渲染、图层合成"] Battery --> Screen["屏幕显示、亮度、刷新率"] Battery --> Network["网络蜂窝、WiFi、BLE"] Battery --> Location["定位GPS、基站、WiFi定位"] Battery --> Sensor["传感器加速度计、陀螺仪、气压计"] Battery --> Audio["音视频录制、播放、相机"] Battery --> Storage["存储磁盘IO"] Battery --> IO["外设蓝牙、NFC、UWB"] 不同硬件模块的功耗量级差异很大。参考苹果WWDC的数据,定位和蜂窝数据通常是"耗电大户",屏幕是"持续耗电大户",而CPU/GPU在计算密集时瞬时功耗最高。 模块 典型功耗等级 特点 屏幕 持续高 只要亮屏就持续耗电 蜂窝数据 高 搜索基站、维持连接都耗电 GPS定位 高 冷启动搜星耗电特别明显 CPU/GPU 中~高 计算量决定功耗 WiFi 中 比蜂窝省电 蓝牙(BLE) 低 低功耗蓝牙专为续航优化 传感器 低~中 高频采样会显著增加功耗 耗电问题的本质 耗电问题的本质可以用一个简单的公式表示: ...

May 8, 2026