一次刨根问底的socket收包过程(Linux)

前言:

在一次socket的收包过程中,会因为一些系统因素带来一定的延迟,下面来讲述这些系统因素。

过程:

Linux会对一个网络包(packet)的收和发做大量的处理。packet在被发送之前会被存在队列中,而在被接收之后也会存在队列中,共有三个队列:reception(接收),transmission(发送)和Backlog。它们都受到spinlock的保护,是为了保证在并发访问时的一致性。言归正传,接下来看看当一个packet到达NIC(网卡)时,linux都会做些什么工作。

先来看一个图(来自论文Analysis of Linux UDP Sockets Concurrent Performance)

1)先触发硬中断(HardIRQ),再进行软中断(SoftIRQ)。

2)软中断执行过程中的Lower Processing处理会将packet从L2层送到L4层。

3)接下来就是packet入队,同步原语会影响到收包性能。(再之后就是被应用程序读取)

补充一点:就拿收包来说,在被应用程序读到之前,linux要将其从网卡搬到内核内存(kernel’s memory),但是一个socket只能使用有限制的内核内存来存包,否则会让内核内存溢出(overflow)。

更详细的收包过程可以看这篇文章:The performance analysis of linux networking – packet receiving。

这篇文章也把收包过程分成了三个更清晰的阶段:

1)网卡驱动程序将packet从NIC搬到ring buffer中,这就是常说的DMA过程

2)接下来触发软中断(SoftIRQ),linux kernel会参与进来,将packet从ring buffer搬到socket的接收缓冲区里。

3)最后就是我们最熟悉的,应用程序从缓冲区里读取packet,就是C语言socket编程中的recv函数,它会进行一个系统调用来读取packet。

补充一点:同样在阶段2中,也是要访问lock的,我们在之前提到过三个接收队列,其中一个叫Backlog,当socket处于被锁状态时,packet就暂存在Backlog中以待进一步处理。

目的:

在普通的i5笔记本上,我们发现一次socket的loopback的TCP的发(client)和收(server)要耗时100~200 us。而loopback的带宽可以达到30~40Gbps,所以并不是网络传输产生这样的延迟(latency)。通过上面的分析,当server这端的网卡收到包时,会经过一系列的步骤才能被用户程序读取,,这一过程包括触发中断,内核内存拷贝,进入带锁的队列,等。会不会是这些操作占据了大部分时间,现在仍不能断言就是,仍然需要更确凿的证据。

刨了这么多,在Dolphin SuperSockets的介绍中发现这个figure:

这两幅图佐证了确实需要十几微秒或几十微秒的时间去处理除了packet网络传输之外的其他操作,而这个SuperSockets之所以能减少其中的延迟,一定是针对我们上面所提的几个阶段进行了优化。

在文章 Architectural Breakdown of End-to-End Latencyin a TCP/IP Network中,有这样的话:

For a small message of 64B,latency with Infiniband was measured at 5.3s and Myrinet at 8.3s compared to60 s on Ethernet with TCP/IP.

… …

It may be obvious why TCP/IP has a much higher latency than Infiniband and Myrinetand other hardware based protocols to efficiently pass point-to-point messagesbetween applications. Key to the differences is that, in the case of Infiniband and Myrinet,the hardware supports the packetization, segmentation, reassembly and movementof payload data into user space. This is directly accessible by the user space applicationwithout a transition from kernel space to user space with memory copies or complexpointer redirection.

… …

另外这里还涉及上下文切换:应用程序并没有运行在正在处理packet的core上。Linux为此会花费 2 us 的overhead。

在这篇文章结尾,总结了四个地方会带来 12~282 us 的latency:

1) head-of-queue effect

2) system bandwidth contention

3) application core affinity

4) interruptand timer

家!甜蜜的家!天下最美好的莫过於家

一次刨根问底的socket收包过程(Linux)

相关文章:

你感兴趣的文章:

标签云: