Linux TCP 单机优化

TCP 的 send 函数 tcp_sendmsg/tcp_sendpage,要调用 lock_sock(sk)。

TCP 的 recv 函数 tcp_recvmsg,也要调用 lock_sock(sk):

void lock_sock_nested(struct sock *sk, int subclass)
{
        might_sleep();
        spin_lock_bh(&sk->sk_lock.slock);
        if (sk->sk_lock.owned)
                __lock_sock(sk);
        sk->sk_lock.owned = 1;
        spin_unlock(&sk->sk_lock.slock);
        /*
         * The sk_lock has mutex_lock() semantics here:
         */
        mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
        local_bh_enable();
}

__lock_sock 的核心即睡眠等锁。

这意味着 TCP socket 的 send 和 recv 互斥。睡眠等锁期间,CPU 时间不属于该 socket。

不光如此,软中断上下文 tcp_v4_rcv 处理 TCP 接收间,无论 send 还是 recv 均会在一个 spinlock 自旋,这意味着软中断 TCP 接收间,send 无法进行,recv 亦无法读取已按序齐整排入 receive queue 的数据。

这就是我常说的,TCP 称全双工传输,但 Linux TCP 实现却是半双工。我并不认为这是高尚的:
Linux TCP并不是全双工的

很多人怼我,说我根本不懂双工的概念,涉及到物理层,信道。我想他们并没有理解我在说什么。再解释也苍白,引用 iperf-2.0.14a 的 manual 来解释 socket 双工:

–full-duplex
run a full duplex test, i.e. traffic in both transmit and receive directions using the same socket

在我看来,高尚的做法是只保护读写共享的数据,细化锁粒度:

  • sk_write_queue:发送队列,socket 进程上下文写入,tcp_write_xmit 进程上下文或软中断上下文摘除。
  • tcp_rtx_queue:重传队列,socket 进程上下文或软中间上下文写入,tcp_clean_rtx_queue 软中断上下文摘除。
  • sk_receive_queue:接收队列,socket 进程上下文 release_sock 或软中断上下文写入,socket 进程上下文摘除。

保护好这些数据结构,再小心翼翼处理一下其它共享元数据,send/recv/tcp_v4_rcv 即可并行。事情会高尚很多。

迄今为止,我想因为 Linux TCP 单机性能尚未触及瓶颈,拆锁重构工作量成本不小,却没有眼见的收益,社区没人闲着做这事。如今 100 Gbps 网卡越来越多,这些细节早晚会被盯上。

但还有一条路,若 DPDK 可实现好用的 TCP,内核协议栈可能就这么放着永远不动了:

  • DPDK 提供高性能版本 TCP。
  • Kernel 提供通用完备 TCP。

外说一句,曾经 UDP 也是类似 lock_sock,可能也是因为一把梭哈实现简单,后面随着 UDP 应用逐步推广,可能是 QUIC 加持也可能不是,UDP 的 lock_sock 消失了,锁粒度细化到保护特定的共享 queue,最终,连 queue 都拆成了两个,便于批量处理:

  • Linux内核UDP收包为什么效率低?能做什么优化?
  • Linux内核UDP收包为什么效率低?能做什么优化?

这也是历史发展的轨迹。

弄蟹!80块钱弄蟹,两大四小。

浙江温州皮鞋湿,下雨进水不会胖。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值