2. 多核数据处理性能瓶颈定位

在 Layerscape 平台上做多核数据面优化,最忌讳“凭感觉调参”。LS1046A、LS2088A 这类 SoC 同时具备多个 ARM64 核、DPAA1/DPAA2 加速器、共享 L3 与 DDR 控制器,瓶颈可能出现在核间锁竞争、缓存一致性流量、加速器队列拥塞或内存带宽饱和等完全不同的位置。定位的本质,是用三类互补的观测手段把“症状”映射到“资源”:perf 看 CPU 侧的时间去向,DPAA 计数器看加速器与队列的吞吐和丢弃,内存带宽监测看 DDR 与互连是否已经饱和。三者缺一,结论就容易误判。

一、先建立“资源—指标—工具”的对应关系

定位前先明确观测对象。多核数据面常见的四类瓶颈及其可观测信号如下:

  • 核间竞争:多个核争抢同一把自旋锁、同一无锁队列的 cacheline,表现为 perf 中 cycles 高但 instructions 低、IPC 下降,且 context-switches 或 cpu-migrations 异常。
  • 缓存颠簸:共享数据在 L1/L2 之间反复失效,表现为 L1-dcache-load-misses、LLC-load-misses 占比升高,而 DDR 带宽并未打满。
  • 加速器闲置:DPAA 的 SEC、PME、FMan 端口利用率低,但 CPU 却在做本应卸载的工作,表现为 CPU 忙、加速器计数器空闲。
  • 内存带宽饱和:DDR 读写接近峰值,所有核的 stall 都上升,此时加核无效。

下图给出从“现象”到“工具”再到“判定”的定位路径,可作为排查时的对照图。

多核数据面瓶颈定位路径 现象(症状) • 吞吐上不去,加核无效 • 单核延迟抖动大 • CPU 占用高但转发低 • 丢包集中在某队列 • 加速器利用率偏低 • 内存延迟明显上升 观测工具 perf cycles / IPC / cache-miss sched / lock 事件 DPAA 计数器 FMan / SEC / QMan 队列深度 / 丢弃 内存带宽监测 DDR 读写带宽 / 利用率 / 延迟 perf stat -e armv8_pmuv3 内存事件 判定结论 IPC 低 + 锁事件多 → 核间竞争 cache-miss 高 + DDR 未满 → 缓存颠簸 CPU 忙 + 加速器空闲 → 加速器闲置 DDR 利用率 > 85% → 内存带宽饱和 perf 采样示例:定位核间竞争与缓存颠簸 # 采样 5 秒,观察各核 IPC 与缓存事件 perf stat -a -e cycles,instructions, L1-dcache-load-misses,LLC-load-misses \ -C 0-3 sleep 5 # 记录锁竞争与调度事件 perf record -a -e sched:sched_switch \ -e contention 2>/dev/null -- sleep 5 示例输出(假设值,仅作判读演示) CPU0: IPC 0.42 L1miss 18% LLCmiss 9% CPU1: IPC 0.39 L1miss 21% LLCmiss 11% CPU2: IPC 0.95 L1miss 4% LLCmiss 2% CPU3: IPC 0.91 L1miss 5% LLCmiss 3% 判读:CPU0/1 IPC 低且 miss 高, 疑似共享数据竞争或缓存颠簸。

二、perf:把 CPU 时间拆到事件上

perf 的价值在于把“CPU 很忙”拆成可归因的事件。对多核数据面,建议先做一次全局采样:

perf stat -a -e cycles,instructions,cache-misses,\
  L1-dcache-load-misses,LLC-load-misses,\
  context-switches,cpu-migrations -C 0-3 sleep 5

判读要点:IPC = instructions / cycles。若某几个核 IPC 明显低于其他核,而 L1-dcache-load-misses 与 LLC-load-misses 同时偏高,说明这些核在反复访问被其他核修改的共享数据,典型场景是每核都在更新同一个统计计数器、同一个 ring 的 head/tail 指针,或共享连接表。此时应优先做数据分片(per-core 计数、per-core 队列),而不是继续加核。

若 IPC 低但 cache miss 不高,则更可能是锁等待。可用 perf record -e sched:sched_switch 或 perf lock 观察等待热点,再结合 perf report 定位到具体函数。注意:Layerscape 的 PMU 事件名与内核版本相关,ARMv8 常用 armv8_pmuv3_0/... 前缀,先用 perf list 确认可用事件,避免事件名写错导致计数为 0 而误判。

三、DPAA 计数器:判断加速器是否真的在干活

DPAA1 与 DPAA2 的观测入口不同。DPAA1(如 LS1046A)常用 ethtool -S 查看 FMan 端口统计,用 cat /sys/kernel/debug/dpaa/... 或 dpaa_eth 相关节点查看队列与丢弃;DPAA2(如 LS2088A)通过 restool 与 /sys/class/net/*/statistics、MC 的 DPNI/DPIO 计数观察。关键指标包括:

  • FMan 端口 rx/tx 帧数与丢弃:若 rx 有帧但 tx 明显少,且 tx_dropped 上升,说明出口队列拥塞或 CPU 侧消费不及时。
  • QMan 队列深度与入队/出队速率:入队远大于出队,说明消费者(核或加速器)跟不上。
  • SEC 加解密请求数与完成数:请求多、完成少,说明 SEC 通道拥塞;请求少而 CPU 在做加解密,说明卸载未生效。
  • PME 模式匹配命中数:若命中为 0 而 CPU 在做分类,说明规则未下发或未启用。

一个常见误判是“看到 CPU 忙就加核”。如果 DPAA 计数器显示 SEC 完成数已接近通道上限,加核只会让请求排队更长。正确做法是先确认加速器是否饱和:若加速器利用率低而 CPU 忙,应检查是否走了慢路径(如未绑定正确的 queue、未启用 offload、缓冲区未对齐导致回退到软件路径)。

四、内存带宽监测:确认是否已到 DDR 天花板

Layerscape 的 DDR 带宽是共享资源,多核同时读写大包时极易打满。可用两类方法:一是通过 PMU 的内存相关事件估算,例如在支持的系统上使用 perf stat -e armv8_pmuv3_0/l3d_cache_refill/ 等事件观察 L3 缺失与回填;二是直接读取 DDR 控制器的性能计数器(部分 BSP 提供 debugfs 节点,如 /sys/kernel/debug/ddr/perf 或厂商提供的 ddr_perf 工具),得到读写字节数与利用率。

判读原则:若 DDR 利用率持续高于约 85%,且各核 stall 同步上升,则瓶颈在内存子系统,此时优化方向是减少访存(数据分片、批量处理、避免跨核共享写)、提高缓存命中,或把可卸载的工作交给 DPAA 加速器以减少 CPU 访存。若 DDR 利用率不高但延迟上升,则更可能是访问模式问题(随机小包、跨 NUMA/跨 cluster 访问),需要调整数据布局与核绑定。

三类工具应交叉验证:perf 给出“哪个核、哪个函数”,DPAA 计数器给出“哪个加速器、哪个队列”,内存带宽给出“是否已到硬件上限”。只有三者指向同一资源时,结论才可靠。

五、一个可复用的排查顺序

  1. 先用 perf stat -a 看全局 IPC 与 cache miss,判断是计算密集还是访存/同步密集。
  2. 若 IPC 低且 miss 高,查共享写与 cacheline 伪共享;若 IPC 低且 miss 不高,查锁与调度。
  3. 同时读 DPAA 计数器,确认 FMan/SEC/QMan 是否有丢弃、积压或空闲。
  4. 最后看 DDR 利用率,排除内存带宽饱和这一“全局性”瓶颈。
  5. 每次只改一个变量(如数据分片或队列绑定),用同一组命令复测,比较 IPC、丢弃数与带宽的变化。

需要强调的是,上述示例中的数值均为演示用假设值,实际排查必须以目标板卡的 perf list、BSP 提供的 debugfs 节点和 DPAA 版本为准。不同 Layerscape 型号的计数器命名与可访问路径差异较大,先确认工具可用性,再谈优化。