6.1810 / 6.1810 · 第 16 课 · nz

高性能网络 (Shenango)

现代数据中心网络服务器(如 memcached)需要低延迟和高 CPU 效率。Shenango (NSDI 2019) 通过内核旁路(kernel bypass)和 I/O 内核(I/O kernel)的细粒度调度,在低尾延迟和高利用率之间取得平衡。

授课教师:nz

日期:2025 年春季

难度:困难

阅读:Shenango: Achieving High CPU Efficiency for Latency-Sensitive Datacenter Workloads (NSDI 2019)

Linux 网络软件结构

接收路径:
NIC 将收到的包 DMA 到 RX Ring → NIC 中断内核 → 内核处理包(TCP/UDP)
  → 复制到目的 socket 队列 → 唤醒应用的 read

发送路径:
应用发送包 → 插入 TX Ring → NIC 发送包

高性能网络服务器

以 memcached(内存键值存储服务器)为例:

性能指标

尾延迟

来自 Google 著名论文 The Tail at Scale:

延迟组成

低负载高负载
光速 + 交换机往返时间 + 中断 + 队列操作 + sleep/wakeup + 系统调用 + 核间数据移动 + RAM 读取 延迟主要由等待时间(排队)决定

高负载下延迟难以分析:突发到达、突发服务时间、负载不平衡、无人服务队列等结构性问题都会增加排队时间。

相关硬件限制

资源限制
10 Gbps 以太网~1000 万 100 字节包/秒
1 个 2.4 GHz 核心每包 240 周期
8 核心每包 1920 周期
系统调用每秒几百万次
中断每秒 100 万次

结论:太慢了!


解决方案:内核旁路(Kernel Bypass)

Linux 内核给 Shenango NIC 队列和专用核心,然后 Linux 不太参与。

Shenango 用户态库(Figure 2)

内核旁路网络

轮询

应用有专用核心,持续检查 NIC 环是否有新输入。如果总是可能有输入等待,中断是多余的。

好处:低尾延迟

专用资源给应用,无共享资源争用。每个连接一个核心,无锁、无数据移动。


评估

Figure 3

利用率问题

负载LinuxZygOSShenango
高负载核心忙于网络包核心忙于网络包核心忙于网络包
低负载时间分享核心,运行其他应用核心预留,不运行其他应用I/O 内核允许其他应用突发!

数据中心通常以低利用率运行以实现低尾延迟。


Shenango 的解决方案:I/O 内核

I/O 内核是一个有 root 权限的 Linux 进程:

挑战:避免"计算拥塞"

工作因应用没有足够核心而延迟几微秒。I/O 内核必须快速决策。

I/O 内核的位置与职责

检测计算拥塞(Algorithm 1)

核心分配(Algorithm 2)

  1. 优先选择应用已有超线程的核心
  2. 优先选择应用最近 yield 的核心
  3. 选择任何空闲核心(如果有)
  4. 抢占突发应用的随机核心

Shenango 实现

响应负载变化

Figure 3 显示 Shenango 表现良好。Figure 5 直接回答:Shenango 能多快响应负载变化?


总结

高性能网络是困难的!


测验

Q1:内核旁路(kernel bypass)的主要好处是什么?

Q2:为什么尾延迟(tail latency)对大规模服务很重要?

Q3:Shenango 的 I/O 内核的主要创新是什么?

Q4:为什么 Shenango 使用轮询而非中断?

Q5:为什么 I/O 内核自己引导包(而非重新编程 NIC)?

要点总结

尾延迟是核心指标

扇出使高尾延迟影响大量请求。低负载和高负载下都需保持低尾延迟。

内核旁路

专用核心 + 用户态 NIC 访问 + 轮询,消除内核开销和锁争用。

I/O 内核

细粒度核心分配,每 5μs 检测计算拥塞,动态调整。

低延迟 vs 高利用率

通过允许其他应用在空闲核心突发,兼顾两者。

延伸阅读