linux 休眠导致UDP发送/接收延迟增加

ylamdve6  于 2023-03-22  发布在  Linux
关注(0)|答案(1)|浏览(296)

我正在测试UDP环回性能,我发现睡眠线程会导致最小UDP延迟大幅增加。我用C和Rust编写了大致相同的代码,在同一个进程中启动两个线程,发送/接收UDP数据包,并测量sendrecv调用所需的时间。我在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延迟会如此急剧地增加吗?有没有一种技术可以用来抑制传输而不会导致延迟损失?

bkhjykvo

bkhjykvo1#

我在嵌入式系统中遇到了同样的问题。在我的例子中,usleep(10)+ sendto()在一些变化中大约需要80 us。当我设置调度策略和发送/接收线程的优先级时,它会大大减少。

pthread_attr_setschedpolicy(&pthread_attr, SCHED_FIFO);
struct sched_param sched;
sched.sched_priority = sched_get_priority_max(SCHED_FIFO);  // The highest priority
pthread_attr_setschedparam(&pthread_attr, &sched);

顺便说一句,你的usleep(10000)会让你的线程睡眠10 ms,而不是10 us。我希望你的结果在单位内有错别字。

相关问题