eBPF 性能模型
eBPF 性能模型(为什么快 / 与传统方案对比)
先澄清一个常见误解
很多人以为 eBPF 是”绕过了用户态→内核态的上下文切换”。更准确的说法是——eBPF 程序本来就运行在内核态(挂载在 kprobe/XDP/TC/cgroup 等内核 hook 上),它压根不在用户态,所以无所谓”绕过”切换,而是”不需要为每条事件做那次切换”。
真正被省掉的,是传统观测/处理方案里”内核采集 → 切用户态处理 → 切回内核”的每事件往返,以及随之的数据拷贝。
传统方案的三笔账
以抓包统计、syscall 观测为例,传统工具(tcpdump/libpcap、perf、strace)处理每一条事件都要付:
| 开销 | 说明 | 例子 |
|---|---|---|
| 内核→用户态数据拷贝 | 内核把原始数据 copy_to_user 到用户态 buffer | tcpdump 每包都拷、perf 每采样都拷 |
| 上下文切换 / 唤醒 | 用户态要么轮询(空耗 CPU),要么被事件唤醒(每次一次切换) | perf 采样触发中断唤醒用户态 |
| 系统调用往返 | 用户态读数据做决策,常需再 syscall 回内核(改配置、写回) | strace 每次 syscall 都陷入内核再回用户态 |
即:每条事件 = 一次”内核采集 → 切用户态处理 →(可能)切回内核”的往返 + 一次数据拷贝。事件量大时,切换与拷贝本身就吃掉大半 CPU,真正做业务的 CPU 反而少了。
eBPF 把”每事件一次”降为”每聚合一次”
eBPF 把处理逻辑也搬进内核:在内核里就地过滤、聚合(如 bpftrace @us=hist() 直方图直接在内核算好),只通过 BPF Map / ringbuf 把”最终结果”或”极少数的感兴趣事件”传回用户态。用户态进程大部分时间在睡觉,只在周期末来读一次 map。
类比:传统像每个快递都从仓库(内核)搬到门店(用户态)拆包再决定;eBPF 像在仓库里先分拣好,只把要处理的少量件送门店。省掉的是”每条事件都来回切 + 都拷贝”,而非”那一次切换”本身。
网络场景的真正大头:绕过协议栈
对于网络,上下文切换其实是小头,大头是绕过整个 Linux 网络协议栈。
graph LR
subgraph 传统
A1[网卡] --> A2[skb 分配] --> A3[路由] --> A4[Netfilter/iptables 遍历] --> A5[conntrack] --> A6[改写] --> A7[重调度]
end
subgraph eBPF XDP
B1[网卡] --> B2[XDP 决策: drop/redirect/改写] --> B3[直接发出, 不过协议栈]
end
| 路径 | 每包开销 |
|---|---|
| 传统 kube-proxy iptables | skb 分配 → 路由 → Netfilter/iptables 规则遍历 → conntrack → 改写 → 重调度 |
| eBPF XDP | 网卡驱动最早收包点就决定 drop/redirect/改写,不分配 skb、不进协议栈、不过 iptables/conntrack |
这部分省下的 CPU 比省下的上下文切换大一个数量级——这是 Cilium 所谓”零开销数据面”的真正含义,也是 eBPF 与 Cilium K8s 实战 里 KPR 能减负 conntrack 的底层原因。
conntrack 减负量化(结合你的网络笔记)
传统 kube-proxy iptables:每条 Service 连接都要在 nf_conntrack 建一条条目,节点连接数高时 conntrack 表打满就丢包(你 ../网络内核参数调优 里写过这个坑)。
eBPF socket LB 在 socket 层完成 DNAT 重定向,配合 DSR/直接路由,大量连接根本不进 conntrack 表。实测上 Cilium KPR 节点的 conntrack 条目数可比 iptables 模式低一个数量级。
但 KPR ≠ 能完全关掉 conntrack。kubelet、CNI 插件、部分跨节点 NAT 仍需要它——“不能把
nf_conntrack_max设 0”依然成立。
eBPF 与其他高性能方案的对比
| 方案 | 位置 | 优点 | 缺点 |
|---|---|---|---|
| eBPF XDP | 内核驱动层 | 免内核模块、可热更新、与内核协同 | 受内核版本/驱动支持限制 |
| DPDK | 用户态轮询(跳过内核协议栈) | 极致吞吐/延迟 | 独占 CPU、绕开内核(失去 conntrack/iptables) |
| 内核模块 | 内核 | 灵活 | 不安全、易 panic、难维护 |
| 智能网卡/Offload | 硬件 | 零 CPU 占用 | 贵、vendor lock-in |
eBPF 的甜点在”既拿到接近用户态的性能,又不离开内核生态”——这是 DPDK 做不到的。
一句话精准模型
eBPF 的性能收益 = 处理逻辑下沉到内核(避免每条事件的上下文切换 + 数据拷贝)+ 在网络路径最早期决策(绕过协议栈 / iptables / conntrack),而非”绕过用户态转内核态”本身。
关联知识
- eBPF 核心机制与安全 — hook 点与 map 是怎么支撑”下沉内核”的
- eBPF 与 Cilium K8s 实战 — KPR / XDP 在 Cilium 里的落地
- ../网络内核参数调优 — conntrack 压力与 eBPF 替代方案
- ../../k8s/特性详解/nftables kube-proxy 详解 — iptables kube-proxy 的开销对比
学习时间
| 阶段 | 时间 | 备注 |
|---|---|---|
| 性能模型 | 2026-07-16 | 误解澄清、传统三笔账、降频模型、XDP 绕过协议栈、conntrack 量化、与 DPDK 对比 |