4. CPU子系统性能分析与调优

R-Car车载计算平台的CPU子系统通常由多个Cortex-A核(如A76/A55大小核组合)构成,运行Linux与实时任务混合负载。性能问题往往不是单一原因造成的:可能是某个核被单线程任务打满、可能是频率被热约束压低、也可能是任务在核间频繁迁移导致缓存失效。要定位并解决这些问题,需要把perf、ftrace、cpufreq/cpuidle、CPU hotplug和任务亲和性这几类工具组合起来使用,形成"观测—定位—干预—验证"的闭环。

用perf定位热点与调度行为

perf是CPU性能分析的第一入口。面对"系统变慢"这类模糊描述,先用perf stat看整体指标,再用perf top或perf record找热点函数。

# 采样5秒,观察整体CPU行为
perf stat -a -e cycles,instructions,cache-misses,context-switches,cpu-migrations sleep 5

# 记录热点,-g带调用栈
perf record -F 999 -g -a -- sleep 10
perf report --stdio | head -40

关键判读点:instructions per cycle(IPC)偏低说明CPU在等内存或分支预测失败;cache-misses高且伴随大量cpu-migrations,往往意味着任务在核间漂移、L1/L2缓存反复失效;context-switches异常高则可能是锁竞争或调度抖动。在R-Car这类大小核平台上,还要用perf stat -e cpu-clock --per-core分核观察,确认是某个A76核饱和,还是A55核被误调度了重负载。

用ftrace追踪调度延迟与唤醒路径

perf擅长统计,ftrace擅长看时序。当怀疑调度延迟或中断抖动时,用trace-cmd或直接操作tracefs抓取调度事件。

# 抓取调度切换与唤醒事件
echo 1 > /sys/kernel/debug/tracing/events/sched/enable
echo 1 > /sys/kernel/debug/tracing/events/irq/enable
echo function_graph > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/trace_pipe

重点看sched_wakeup到sched_switch之间的时间差,这就是任务的唤醒延迟。如果延迟达到毫秒级,常见原因是目标CPU正处于idle深睡状态(C-state退出慢),或该核被其他高优先级任务占用。配合sched_switch中的prev/next字段,可以还原出"谁抢占了谁",判断是否存在优先级反转或CPU争抢。

cpufreq与cpuidle:功耗与性能的平衡点

R-Car的CPU频率由cpufreq子系统管理,常见governor有schedutil、ondemand、performance。车载场景推荐schedutil,它直接依据调度器的利用率信号调频,响应比ondemand更快。

# 查看当前策略与可用频率
cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
cat /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies

# 切换到schedutil并设置上下限
echo schedutil > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
echo 1200000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq

cpuidle则控制核进入多深的睡眠。C-state越深省电越多,但退出延迟越大。如果ftrace显示唤醒延迟高,可以查看/sys/devices/system/cpu/cpu0/cpuidle/下各状态的latency与usage,必要时用cpuidle.governor=menu或限制最大C-state来降低延迟。功耗与延迟的取舍必须结合具体任务:安全相关的实时任务应避免深睡,而后台批处理任务则可以放宽。

任务亲和性与CPU hotplug

把关键任务绑定到固定核,可以避免迁移带来的缓存失效和延迟抖动。使用taskset或sched_setaffinity设置亲和性:

# 将PID 1234绑定到CPU 2和3
taskset -pc 2,3 1234

# 启动时直接绑定
taskset -c 2 ./adas_perception

在大小核平台上,通常把实时/高吞吐任务绑到A76大核,把轻量后台任务放到A55小核,减少互相干扰。CPU hotplug则用于动态上下线核心:在热约束或低负载时下线部分核以省电,但要注意下线前必须先把该核上的任务迁走,否则会触发迁移开销甚至失败。

# 下线CPU 3(需先确保无任务绑定)
echo 0 > /sys/devices/system/cpu/cpu3/online

下图总结了从观测到干预再到验证的完整分析链路,以及各工具在其中的作用位置。

CPU子系统性能分析链路 ① 观测层 perf stat / perf record ftrace sched / irq 事件 ② 判读层 IPC低 / cache-miss高 唤醒延迟 / 迁移次数 ③ 定位层 热点函数 / 饱和核 频率瓶颈 / 深睡延迟 ④ 干预层:调优手段 cpufreq schedutil调频 min/max频率限制 cpuidle C-state深度控制 退出延迟权衡 亲和性 taskset绑定 大小核分工 CPU hotplug 动态上下线 低负载省电 ⑤ 验证层:回归对比 perf stat 对比调优前后 IPC / 延迟 / 功耗 确认无任务饥饿、无热降频反弹 未达标则迭代

综合调优示例与判断依据

假设某ADAS感知任务在R-Car上出现周期性卡顿。按上述链路:先用perf stat发现cpu-migrations偏高,再用ftrace看到任务在CPU 0~3之间反复迁移,且唤醒延迟约1.2ms。干预措施:将感知线程用taskset -c 4,5绑定到A76大核,把governor设为schedutil并锁定min_freq为1.2GHz,同时限制CPU 4/5的最大C-state为C1以降低唤醒延迟。验证时重新跑perf stat,若cpu-migrations降到接近0、唤醒延迟降到200μs以内、IPC提升,则说明调优有效;若功耗上升超出预算,则需在频率上限和C-state深度之间重新找平衡点。

调优的核心不是"把所有参数拉满",而是先量化瓶颈,再针对性干预,最后用同一组指标验证。perf给统计、ftrace给时序、cpufreq/cpuidle给功耗控制、亲和性与hotplug给资源分配,四者配合才能同时兼顾性能与功耗。