我正在测试UDP环回性能,我发现睡眠线程会导致最小UDP延迟大幅增加。我用C和Rust编写了大致相同的代码,在同一个进程中启动两个线程,发送/接收UDP数据包,并测量send
和recv
调用所需的时间。我在macOS和Linux上都进行了实验。
我发现,在循环中使用sleep()
来减少调用/响应循环实际上会导致recv()
和send()
调用比通常要长得多。
while (1) {
// This sleep causes a large increase in latency
#ifdef ENABLE_SLEEP
usleep(10000);
#endif
double t_pre_send = curr_timestamp();
if (send(sockfd, NULL, 0, 0) == -1) {
perror("send failed");
}
avg_send_elapsed = 0.9*avg_send_elapsed + 0.1*(curr_timestamp() - t_pre_send);
double t_pre_recv = curr_timestamp();
socklen_t len = 0;
int num_bytes = recvfrom(sockfd, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *) &cliaddr, &len);
avg_recv_elapsed = 0.9*avg_recv_elapsed + 0.1*(curr_timestamp() - t_pre_recv);
double curr_time = curr_timestamp();
if (curr_time - last_print > 1.0) {
last_print = curr_time;
printf("[%.1f] send: %.2fus\trecv: %.2fus\n", curr_time - t_start, avg_send_elapsed*1000000, avg_recv_elapsed*1000000);
}
}
结果看起来像这样没有睡眠:
[1.0] send: 4.93us recv: 7.41us
[2.0] send: 4.68us recv: 7.04us
[3.0] send: 4.86us recv: 7.58us
[4.0] send: 4.79us recv: 7.60us
[5.0] send: 4.88us recv: 7.03us
[6.0] send: 4.70us recv: 7.57us
[7.0] send: 4.49us recv: 8.02us
[8.0] send: 4.47us recv: 7.23us
[9.0] send: 4.58us recv: 7.15us
和一些类似的东西与睡眠:
[1.0] send: 23.85us recv: 102.13us
[2.0] send: 35.41us recv: 78.07us
[3.0] send: 70.47us recv: 141.07us
[4.0] send: 29.90us recv: 107.35us
[5.0] send: 45.17us recv: 194.27us
[6.0] send: 32.49us recv: 117.74us
[7.0] send: 32.25us recv: 117.83us
[8.0] send: 35.48us recv: 85.67us
[9.1] send: 33.86us recv: 108.71us
我希望睡眠可以调整我们每秒执行的循环迭代次数,但我不希望它影响运行send()
和recvfrom()
函数调用所需的时间。有人能解释为什么我的UDP延迟会如此急剧地增加吗?有没有一种技术可以用来抑制传输而不会导致延迟损失?
1条答案
按热度按时间bkhjykvo1#
我在嵌入式系统中遇到了同样的问题。在我的例子中,usleep(10)+ sendto()在一些变化中大约需要80 us。当我设置调度策略和发送/接收线程的优先级时,它会大大减少。
顺便说一句,你的usleep(10000)会让你的线程睡眠10 ms,而不是10 us。我希望你的结果在单位内有错别字。