本文目录导读:

对 tcp_autocorking(自动塞子)进行基准测试,主要是为了衡量在小数据包或小块写入场景下,该特性对吞吐量、延迟和 CPU 利用率(特别是上下文切换次数)的影响。
由于这是一个内置于 Linux 内核网络栈中的优化机制(而非单独的模块),你不能像测试磁盘 IO 那样直接跑一个单一的 tcp_autocork_bench 工具,你需要通过模拟特定应用模式并对比开启/关闭该特性的结果来进行基准测试。
以下是进行此类基准测试的标准方法、关键指标和具体操作步骤。
核心思路:对比实验
- 开启状态(默认):
/proc/sys/net/ipv4/tcp_autocorking = 1 - 关闭状态:
/proc/sys/net/ipv4/tcp_autocorking = 0
在这两种状态下,运行相同的网络负载测试,对比结果。
基准测试目标(测量什么)
tcp_autocorking 主要影响以下三点:
- 吞吐量(Throughput):对于小块、突发性的写入,是否因合并为更大的 TCP 段而提升了带宽利用率。
- 尾部延迟(Tail Latency):是否因为等待数据填满而增加了某些数据包的延迟。
- 系统调用开销(Context Switches / CPU):是否减少了
send/write系统调用次数和网络栈的处理次数。
测试方法(用标准工具模拟负载)
由于没有专门的 tcp_autocork_bench,你必须用网络基准工具来模拟应用层小块写入。
使用 netperf 模拟小块写入
netperf 可以指定发送消息的大小 (-m)。
-
测试场景:模拟 HTTP/Redis 等应用的小块写入(例如每次写入 1~200 字节)。
-
命令示例:
服务端:
netserver
客户端(开启 autocorking):
# 模拟每次 send 1460 字节(通常是 TCP MSS 的边界) netperf -H <server_ip> -l 30 -t TCP_STREAM -- -m 1460 # 模拟每次 send 200 字节(小块写入,正是 autocorking 起作用的地方) netperf -H <server_ip> -l 30 -t TCP_STREAM -- -m 200
-
对比方法:
- 执行
echo 0 > /proc/sys/net/ipv4/tcp_autocorking。 - 再次运行
netperf -H <server_ip> -l 30 -t TCP_STREAM -- -m 200。
- 执行
-
关注点:
- 当
-m 200时,开启状态应比关闭状态吞吐量更高(因为主机将不完整的 TCP 段推迟发送,等缓冲区有更多数据后再批量发送)。 -m 1460接近 MSS,两者的吞吐量差异应该极小。
- 当
使用 neper(更现代的测试工具)
Neper 是 Netperf 的继任者,提供了更细粒度的控制。
-
安装:
git clone https://github.com/google/neper.git && make -
测试例子:
服务端:
./tcp_rr -s
客户端(开启 autocorking,模拟小消息 ping-pong):
./tcp_rr -H <server_ip> -l 30 -T 4 --msg-size=100 -R 20000
(这表示发送 100 字节的消息,限制速率为 20000 ops/sec,看看延迟)
-
查看延迟分布:Neper 的
tcp_xx工具能输出延迟直方图,你能从中看到开启/关闭 autocorking 对 p99 延迟的影响。
微基准测试(自己写 C 程序)
这是最准确、最贴近你想测试的“碎片化写入”场景的方式。
-
编写服务端:简单的 accept + read。
-
编写客户端:
// 核心循环 for (int i = 0; i < N; i++) { // 模拟碎片化写入: 每次只 write 很小的一段 write(sock_fd, small_buf, 100); // 写入 100 字节 // 不立即调用 flush 或强制推送 (TCP_NODELAY 关闭时) usleep(10); // 模拟应用层处理延迟,让数据不能立即合并成完整包 } -
测量:使用
perf工具统计系统调用次数和 CPU 使用率。# 开启 autocorking perf stat -e context-switches,syscalls:sys_enter_write ./client # 关闭 autocorking echo 0 > /proc/sys/net/ipv4/tcp_autocorking perf stat -e context-switches,syscalls:sys_enter_write ./client
预期结果:开启 autocorking 时,
write系统调用次数不变(因为用户态还是每次写 100 字节),但内核态处理 TCP 段的次数减少,上下文切换可能降低。
如何解读基准测试结果?
| 特性 | 开启 tcp_autocorking |
关闭 tcp_autocorking |
场景解释 |
|---|---|---|---|
| 吞吐量(小块 200B) | 高 | 低 | 开启后,内核将多个小数据包合并成 1460 字节的段,网络利用率高。 |
| 吞吐量(大块 1448B) | 几乎相同 | 几乎相同 | 数据已经很大,合并作用不明显。 |
| 尾部延迟(p99) | 可能变高 | 低 | 开启后,内核为了等更多数据,会延迟发送,小请求可能被卡住。 |
| CPU 利用率 | 更低 | 高 | 内核处理的数据包数量减少(一个 4K 包顶替了 40 个 100B 包),软中断上下文减少。 |
高级:使用 perf 内核事件
若要进行内核级的精确测量,可以使用 perf 追踪网络栈的 cork 操作:
# 查看内核中在执行 tcp_push 时的行为(需要内核符号支持) perf record -e skb:consume_skb,tcp:tcp_probe -a -g -- sleep 10 perf report
你可以观察在 tcp_autocorking 开启/关闭状态下,tcp_push 被调用的频率和 skb(socket buffer)的合并情况。
如何执行 tcp_autocorking 基准测试
- 明确场景:不是所有场景都适合,该特性在查询-响应型应用(如 Nginx、Redis、Kafka Producer)中作用最大,在流式传输(如大文件下载)中作用很小。
- 关闭 Nagle 算法:
tcp_autocorking与TCP_NODELAY有协同关系,测试时需考虑应用是否设置了TCP_NODELAY(若设置了,autocorking 在绝大多数情况下不会生效)。 - 使用工具:
- Netperf / Neper 最方便,通过
-m小参数模拟。 - 自定义 C 程序 最精确,可控制写入粒度和间隔。
- perf 进行内核级验证。
- Netperf / Neper 最方便,通过
- 对比指标:重点关注 p99 延迟(关闭 autocorking 通常有优势) vs 吞吐量/CPU(开启 autocorking 通常有优势)。
你最终会发现,tcp_autocorking 是一个收益与代价的平衡:它通过牺牲小部分尾部延迟来换取整体吞吐量和 CPU 效率的提升,如果你的应用对延迟极其敏感,关闭它可能更合适。