在最新版本的Linux中,TCP延迟更高

在我的研究小组中,我们最近将我们的机器上的操作系统从Red Hat 6.2升级到了Debian 8.3,并且观察到我们机器之间通过集成的Intel 1G NIC的TCP往返时间从110μs增加到220μs。

起初,我认为这是一个configuration问题,所以我将所有的sysctlconfiguration(例如tcp_low_latency=1 )从未升级的Red Hat机器复制到Debian机器,并没有解决问题。 接下来,我认为这可能是一个Linux分发问题,并在机器上安装了Red Hat 7.2,但往返时间保持在220μs左右。

最后,我认为可能是Linux内核版本问题,因为Debian 8.3和Red Hat 7.2都使用内核3.x,而Red Hat 6.2使用内核2.6。 所以为了testing这个,我安装了Debian 6.0 Linux内核2.6和宾果! 时间又在110微秒。

其他人也在最新版本的Linux中经历了这些更高的延迟,并且有已知的解决方法吗?


最小工作示例

下面是一个C ++应用程序,可用于基准延迟。 它通过发送消息,等待响应,然后发送下一个消息来测量延迟。 它用100字节的消息完成了这个100,000次。 因此,我们可以将客户的执行时间除以100,000来获得往返延迟。 要使用这个首先编译程序:

 g++ -o socketpingpong -O3 -std=c++0x Server.cpp 

接下来在主机上运行应用程序的服务器端版本(比如192.168.0.101)。 我们指定IP以确保我们在一个知名的界面上托pipe。

 socketpingpong 192.168.0.101 

然后使用Unix工具time来测量客户端的执行时间。

 time socketpingpong 192.168.0.101 client 

在两个具有相同硬件的Debian 8.3主机之间运行这个实验会得出以下结果。

 real 0m22.743s user 0m0.124s sys 0m1.992s 

Debian 6.0的结果是

 real 0m11.448s user 0m0.716s sys 0m0.312s 

码:

 #include <unistd.h> #include <limits.h> #include <string.h> #include <linux/futex.h> #include <arpa/inet.h> #include <algorithm> using namespace std; static const int PORT = 2444; static const int COUNT = 100000; // Message sizes are 100 bytes static const int SEND_SIZE = 100; static const int RESP_SIZE = 100; void serverLoop(const char* srd_addr) { printf("Creating server via regular sockets\r\n"); int sockfd, newsockfd; socklen_t clilen; char buffer[SEND_SIZE]; char bufferOut[RESP_SIZE]; struct sockaddr_in serv_addr, cli_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) perror("ERROR opening socket"); bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(srd_addr); serv_addr.sin_port = htons(PORT); fflush(stdout); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { perror("ERROR on binding"); } listen(sockfd, INT_MAX); clilen = sizeof(cli_addr); printf("Started listening on %s port %d\r\n", srd_addr, PORT); fflush(stdout); while (true) { newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) perror("ERROR on accept"); printf("New connection\r\n"); int status = 1; while (status > 0) { // Read status = read(newsockfd, buffer, SEND_SIZE); if (status < 0) { perror("read"); break; } if (status == 0) { printf("connection closed"); break; } // Respond status = write(newsockfd, bufferOut, RESP_SIZE); if (status < 0) { perror("write"); break; } } close(newsockfd); } close(sockfd); } int clientLoop(const char* srd_addr) { // This example is copied from http://www.binarytides.com/server-client-example-c-sockets-linux/ int sock; struct sockaddr_in server; char message[SEND_SIZE] , server_reply[RESP_SIZE]; //Create socket sock = socket(AF_INET , SOCK_STREAM , 0); if (sock == -1) { printf("Could not create socket"); } puts("Socket created"); server.sin_addr.s_addr = inet_addr(srd_addr); server.sin_family = AF_INET; server.sin_port = htons( PORT ); //Connect to remote server if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0) { perror("connect failed. Error"); return 1; } printf("Connected to %s on port %d\n", srd_addr, PORT); // Fill buffer for (int i = 0; i < SEND_SIZE; ++i) { message[i] = 'a' + (i % 26); } for (int i = 0; i < COUNT; ++i) { if (send(sock, message, SEND_SIZE, 0) < 0) { perror("send"); return 1; } if ( recv(sock, server_reply, RESP_SIZE, 0) < 0) { perror("recv"); return 1; } } close(sock); printf("Sending %d messages of size %d bytes with response sizes of %d bytes\r\n", COUNT, SEND_SIZE, RESP_SIZE); return 0; } int main(int argc, char** argv) { if (argc < 2) { printf("\r\nUsage: socketpingpong <ipaddress> [client]\r\n"); exit(-1); } if (argc == 2) serverLoop(argv[1]); else clientLoop(argv[1]); return 0; } 

这不是一个答案,但严格校准延迟/吞吐量问题非常重要。 这可能会帮助你更接近答案,甚至可以帮助其他人给你更好的根源过程build议。

尝试使用接口上的wireshark / tshark捕获获取更准确的数据,

  1. 确认吞吐量实际上减半了
  2. 确定延迟如何分布(在tx和rx之间)
    一个。 testing是否统一?
    湾 有没有一个集中摊位?

我查看了更新日志,可能是QFQ的引入

内核3.0networking更新日志https://kernelnewbies.org/Linux_3.0#head-96d40fb6f9c48e789386dbe59fd5b5acc9a9059d

QFQ提交者页面http://info.iet.unipi.it/~luigi/qfq/

它以极低的每包成本提供紧密的服务保证。