c - 测量 Unix 域套接字的延迟

标签 c performance sockets unix benchmarking

我想比较两个进程与另一个 IPC 之间的 Unix 域套接字的性能。

我有一个创建套接字对然后调用 fork 的基本程序。然后,它测量 RTT 以将 8192 字节发送到另一个进程并返回(每次迭代都不同)。

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

int main(int argc, char **argv) {
    int i, pid, sockpair[2];
    char buf[8192];
    struct timespec tp1, tp2;

    assert(argc == 2);

    // Create a socket pair using Unix domain sockets with reliable,
    // in-order data transmission.
    socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);

    // We then fork to create a child process and then start the benchmark.
    pid = fork();

    if (pid == 0) { // This is the child process.
        for (i = 0; i < atoi(argv[1]); i++) {
            assert(recv(sockpair[1], buf, sizeof(buf), 0) > 0);
            assert(send(sockpair[1], buf, sizeof(buf), 0) > 0);
        }
    } else { // This is the parent process.
        for (i = 0; i < atoi(argv[1]); i++) {
            memset(buf, i, sizeof(buf));
            buf[sizeof(buf) - 1] = '\0';
            assert(clock_gettime(CLOCK_REALTIME, &tp1) == 0);
            assert(send(sockpair[0], buf, sizeof(buf), 0) > 0);
            assert(recv(sockpair[0], buf, sizeof(buf), 0) > 0);
            assert(clock_gettime(CLOCK_REALTIME, &tp2) == 0);
            printf("%lu ns\n", tp2.tv_nsec - tp1.tv_nsec);
        }
    }

    return 0;
}

但是,我注意到对于每次重复测试,第一次运行 (i = 0) 的运行时间始终是异常值:

79306 ns
18649 ns
19910 ns
19601 ns
...

我想知道内核是否必须在第一次调用 send() 时进行一些最终设置 - 例如,在内核中分配 8192 字节来缓冲 调用之间的数据发送()recv()

最佳答案

不是数据复制需要额外 80 微秒,那会非常慢(仅 100 MB/s),而是您使用两个进程并且当父进程第一次发送数据时,这些数据需要等待child完成fork并开始执行。

如果你绝对想使用两个进程,你应该先执行另一个方向的发送,这样父进程就可以等待子进程准备好 开始发送。

例如: child :

  send();
  recv();
  send();

家长:

  recv();
  gettime();
  send();
  recv();
  gettime();

您还需要意识到,您的测试在很大程度上取决于各种 CPU 内核上的进程布局,如果在同一内核上运行,将导致任务切换。

因此,我强烈建议您进行测量 使用单个进程。即使没有民意调查也没有任何东西,你可以这样做 前提是您保留适合套接字缓冲区的相当小的 block :

gettime();
send();
recv();
gettime();

您应该首先执行非测量往返以确保分配缓冲区。我很确定您在这里的时间会少得多。

关于c - 测量 Unix 域套接字的延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31744268/

相关文章:

c# - 如何对 MySQL 查询进行排队,使它们顺序进行而不是并发,并防止过度使用 I/O?

python - 为什么我的 python 程序在 eclipse/pydev 中调试这么慢?

c++ - 如何正确渲染 3ds 文件中的面孔

c - linux execve,段错误(strcmp_sse42)

java - 如何在 Java Flight Recorder 采样中包含 IO 绑定(bind)方法?

android - Android 上类似 teamviewer 的应用程序技术

sockets - 使用单个 SSH 连接在远程计算机上使用多个终端

python - 如何使用套接字将文件从flutter应用程序发送到python服务器

android - NDK从 native 代码调用函数

c - 无符号字符比较