Ste*_*hen 8 networking linux performance latency tcp
在我的研究小组中,我们最近将我们机器上的操作系统从 Red Hat 6.2 升级到 Debian 8.3,并观察到我们机器之间通过集成 Intel 1G NIC 的 TCP 往返时间从大约 110µs 增加到 220µs。
起初,我以为是配置问题,所以我将所有tcp_low_latency=1未升级的Red Hat机器的sysctl配置(例如)复制到Debian机器上,但并没有解决问题。接下来,我认为这可能是 Linux 发行版的问题,并在机器上安装了 Red Hat 7.2,但往返时间仍然在 220µs 左右。
最后,我认为问题可能出在 Linux 内核版本上,因为 Debian 8.3 和 Red Hat 7.2 都使用了内核 3.x,而 Red Hat 6.2 使用了内核 2.6。所以为了测试这一点,我安装了带有 Linux 内核 2.6 和宾果游戏的 Debian 6.0!时间再次加快,为 110µs。
其他人在最新版本的 Linux 中是否也遇到过这些更高的延迟,是否有已知的解决方法?
下面是一个 C++ 应用程序,可用于对延迟进行基准测试。它通过发送消息、等待响应,然后发送下一条消息来测量延迟。它使用 100 字节的消息执行 100,000 次此操作。因此,我们可以将客户端的执行时间除以 100,000 以获得往返延迟。要使用它首先编译程序:
g++ -o socketpingpong -O3 -std=c++0x Server.cpp
Run Code Online (Sandbox Code Playgroud)
接下来在主机(比如 192.168.0.101)上运行应用程序的服务器端版本。我们指定 IP 以确保我们托管在众所周知的接口上。
socketpingpong 192.168.0.101
Run Code Online (Sandbox Code Playgroud)
然后使用 Unix 实用程序time来测量客户端的执行时间。
time socketpingpong 192.168.0.101 client
Run Code Online (Sandbox Code Playgroud)
在具有相同硬件的两台 Debian 8.3 主机之间运行此实验会得到以下结果。
real 0m22.743s
user 0m0.124s
sys 0m1.992s
Run Code Online (Sandbox Code Playgroud)
Debian 6.0 结果是
real 0m11.448s
user 0m0.716s
sys 0m0.312s
Run Code Online (Sandbox Code Playgroud)
代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
这不是答案,但严格校准延迟/吞吐量问题很重要。它可能会帮助您更接近答案,甚至可以帮助这里的其他人为您提供有关根本原因过程的更好建议。
尝试在接口上 使用wireshark /tshark捕获来获取更准确的数据,