3. 网络性能指标与瓶颈分析:吞吐量、延迟、丢包率、CPU占用率;如何用perf/top定位瓶颈

各位同学,咱们今天聊点实在的。做车载网络优化,说白了就是跟四个数字打交道:吞吐量、延迟、丢包率、CPU占用率。这四个指标就像汽车的四个轮子,哪个出问题车都跑不稳。

我个人习惯,拿到一个网络性能问题,先不看代码,先看这四个指标。为什么?因为它们能告诉你问题的大致方向。就像医生看病先量体温测血压一样,方向对了,后面才能精准下药。

3.1 四大核心指标详解

3.1.1 吞吐量(Throughput)

吞吐量,说白了就是单位时间内能传多少数据。车载场景下,我一般关注两个维度:

  • 链路层吞吐:比如CAN总线、以太网物理层的极限速率
  • 应用层吞吐:实际业务能拿到的有效带宽

我在项目中遇到过一件事:某款车机用千兆以太网,但实际传输视频流时只有200Mbps。一开始以为是硬件问题,后来一查,是协议栈的socket buffer太小,导致频繁丢包重传。嗯,这里要注意,硬件标称值和实际吞吐量之间,往往差着一个协议栈优化的距离。

关键公式:有效吞吐量 = 理论带宽 × (1 - 丢包率) × 协议效率因子

这个公式我经常写在白板上,提醒自己和团队:丢包率对吞吐量的影响是指数级的,不是线性的。

3.1.2 延迟(Latency)

延迟分好几种,咱们做车载的尤其要分清楚:

延迟类型 定义 车载典型场景
处理延迟 CPU处理数据包的时间 ADAS传感器数据解析
排队延迟 数据包在缓冲区等待的时间 多路视频流同时传输
传输延迟 数据在物理介质上传播的时间 以太网帧从ECU A到ECU B
协议延迟 协议栈处理(如TCP三次握手) 远程诊断连接建立

你想想看,车载场景下,延迟敏感度是分级的。比如刹车信号,延迟超过10ms就可能出事故。而OTA升级包,延迟几百毫秒都没事。所以分析延迟时,一定要结合业务场景。

3.1.3 丢包率(Packet Loss)

丢包率这个指标,我吃过不少亏。曾经有一次,客户反馈车机播放视频卡顿,我查了三天,发现是网卡驱动在特定中断频率下会偶尔丢包。丢包率只有0.1%,但对视频流来说,这0.1%就足以让画面撕裂。

避坑指南:我曾经以为丢包率低于1%就没事,直到做车载视频流测试时被打脸。对于实时音视频,丢包率超过0.1%就能感知到。对于CAN总线控制信号,丢包率必须为0。

丢包的原因通常有这几个:

  • 缓冲区溢出(最常见)
  • 网卡硬件故障或驱动bug
  • 链路层冲突(尤其是半双工模式)
  • TCP重传超时

3.1.4 CPU占用率

这个指标容易被忽视。很多人觉得CPU占用率跟网络性能没关系,其实关系大了去了。网络协议栈的处理是要吃CPU的,尤其是中断处理和数据拷贝。

我记得有一次,某款车机在播放高清地图时,网络吞吐量突然下降。用top一看,ksoftirqd进程占了60%的CPU。说白了,中断处理把CPU吃光了,应用层拿不到时间片,吞吐量自然上不去。

我的经验:网络相关的CPU占用率,重点关注这几个进程:

  • ksoftirqd/* - 软中断处理
  • net_rx_action - 网络接收处理
  • 应用进程本身(比如视频解码线程)

如果软中断占用超过30%,基本可以断定协议栈有瓶颈。

3.2 用perf定位瓶颈

perf这个工具,我几乎天天用。它就像网络协议栈的CT机,能扫描出每个函数的热点。

3.2.1 基本用法

# 采样网络相关事件
perf record -e cycles:u -g -p <pid> -- sleep 10

# 查看热点函数
perf report

# 查看网络栈的调用链
perf script | grep -E "tcp|ip|net"

我个人习惯,先跑一个全局采样,看看CPU到底花在哪里。如果发现大量时间花在tcp_recvmsgip_rcv上,那就说明协议栈处理是瓶颈。

3.2.2 实战案例

有一次,我遇到一个吞吐量上不去的问题。用perf一看,发现skb_copy_datagram_iovec这个函数占了40%的CPU。说白了,数据从内核态拷贝到用户态太频繁了。

解决方案是什么?启用零拷贝(Zero-Copy)机制。用splice()系统调用替代read(),避免数据在内核和用户空间之间来回拷贝。改完之后,吞吐量直接翻倍。

perf常用网络事件

# 查看网络设备中断分布
perf stat -e irq:irq_handler_entry -a -- sleep 5

# 查看TCP重传
perf stat -e tcp:tcp_retransmit_skb -a -- sleep 10

# 查看socket缓冲区状态
perf stat -e sock:sock_exceed_buf_limit -a -- sleep 5

3.3 用top定位CPU瓶颈

top命令虽然简单,但用好了也能快速定位问题。我一般这样用:

# 按CPU占用排序
top -o %CPU

# 查看每个CPU核心的负载
top -1

# 查看特定进程的线程级CPU占用
top -H -p <pid>

你想想看,如果某个CPU核心的软中断占用(si列)特别高,比如超过20%,那基本可以断定这个核心被网络中断淹没了。解决方案通常是调整中断亲和性(IRQ affinity),把中断分散到多个核心上。

3.3.1 中断亲和性调整

# 查看网卡中断号
cat /proc/interrupts | grep eth0

# 设置中断亲和性(假设中断号是47)
echo 2 > /proc/irq/47/smp_affinity  # 绑定到CPU1

我曾经在一个四核平台上,把所有的网络中断都绑定到了CPU0上。结果CPU0的软中断占用达到80%,其他三个核心闲得发慌。调整之后,吞吐量提升了30%。

注意:调整中断亲和性时,要避免把中断和关键应用绑在同一个核心上。否则应用和中断抢CPU,两边都跑不好。

3.4 综合诊断流程

说了这么多,我总结一个我自己常用的诊断流程:

  1. 先看宏观指标:用netstat -s看丢包、重传、窗口收缩等统计
  2. 再看CPU分布:用top看软中断和进程CPU占用
  3. 深入采样:用perf定位热点函数
  4. 针对性优化:根据瓶颈类型选择优化手段

这个流程我用了好几年,基本没失手过。说白了,网络性能优化就是一场「找瓶颈」的游戏。找到瓶颈,解决它,然后找下一个瓶颈。直到所有指标都达标为止。

小技巧:车载环境下,建议在测试时同时记录这四个指标的时间序列数据。这样出了问题,可以回放分析,看看是哪个指标先异常的。我习惯用sar -n DEV 1记录网络统计,配合perf script的时间戳,能精确到毫秒级定位问题。

好了,这一章的内容就到这里。下一章咱们聊聊具体的优化手段,比如如何调整socket缓冲区大小、如何优化中断处理、如何启用硬件卸载功能。这些都是在实际项目中能立竿见影的技巧。