对应路线图:Phase 1 (Day 22-49) | DPDK 24.11.6 LTS | 内核对照 v6.6
代码出处:source/dpdk-stable-24.11.6/与source/linux-stable/,引用均标文件:行号
上一篇:P1-05 PMD | 下一篇:P1-07 RSS
一句话定位
NUMA 是 DPDK 性能模型的第一条纪律:lcore 只用本 socket 的内存和队列。违反了它,前面学的 mempool/ring 免锁优化全部白费——跨 socket 的 UPI 延迟比共享缓存行更疼。
拓扑与代价
lstopo画拓扑;/sys/devices/system/node/node*/distance看距离矩阵。- 跨 socket 内存访问延迟 +50%~100%。实验:同 socket vs 跨 socket 跑 mempool alloc 延迟对比,数据留档
perf-data/P1/。
三条纪律的代码依据
纪律 1:lcore 绑核
worker 线程创建即绑核(lib/eal/linux/eal.c:1197-1224),主线程自己也绑(eal.c:1183-1188):
if (rte_thread_set_affinity_by_id(rte_thread_self(),
&lcore_config[config->main_lcore].cpuset) != 0) {
rte_eal_init_alert("Cannot set affinity");
rte_errno = EINVAL;
return -1;
}绑核 → 线程不迁移 → per-lcore 结构免锁成立(P1-02/03 的所有"免锁"都建立在这条之上)。
纪律 2:内存对齐
mempool 创建必须传目标 socket_id(文档见 rte_mempool.h:1061-1064):
* @param socket_id
* The *socket_id* argument is the socket identifier in the case of
* NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
* constraint for the reserved zone.mempool 结构体本身也记录了这个值:int socket_id; /**< Socket id passed at create. */(rte_mempool.h:239)。
纪律 3:队列对齐
用 rte_eth_dev_socket_id(port) 校验网卡队列与 lcore 同 socket;跨 socket 收包同样有 UPI 延迟惩罚。绑核策略实验:HT 兄弟核 vs 物理核的 PPS 差异——别把两个数据面 lcore 绑在同一物理核的 HT 对上(共享执行单元)。
service core:管理任务的家
rte_service 框架:统计收集、链路检测、定时任务注册成 service,映射到专用 core(rte_service_map_lcore_set)。在 rte_eal_init 中,service 初始化安排在 bus_probe 之前(eal.c:1234),因为 vdev 设备探测时就可能注册 service。数据面 lcore 保持纯净 run-to-completion,管理任务绝不混入热路径。
🐧 内核对照
mm/mempolicy.c:set_mempolicy/mbind 是内核的 NUMA 绑内存 API;调度域(kernel/sched/topology.c)让调度器感知 NUMA 距离。
内核靠调度器"尽量"局部化,DPDK 靠程序员"强制"局部化——这是性能模型的分水岭。内核里 mbind 是"建议",DPDK 里 socket_id 是"契约"。
面试 2 问
- DPDK 应用怎么保证内存不跨 socket? → 创建 mempool/ring 时传目标 socket_id;lcore 绑核到该 socket;分配前
rte_socket_id()校验。 - service core 解决什么问题? → 让管理/控制任务不打断数据面轮询节奏,保持热路径无杂务。
🔧 动手实验
lstopo画本机拓扑图,标出网卡所在 socket;- 同/跨 socket mempool alloc 延迟对比 + ring 吞吐对比,数据留档
perf-data/P1/。
评论 (0)