C 测量Unix域套接字的延迟

C 测量Unix域套接字的延迟,c,performance,sockets,unix,benchmarking,C,Performance,Sockets,Unix,Benchmarking,我想比较两个进程与另一个IPC进程之间Unix域套接字的性能 我有一个基本程序,创建一个套接字对,然后调用fork。然后,它测量RTT以将8192字节发送到另一个进程并返回(每个迭代都不同) 我想知道内核是否必须在第一次调用send()时进行一些最终设置-例如,在内核中分配8192字节,以在调用send()和recv()之间缓冲数据 我猜,涉及的内核代码的指令缓存未命中是第一次到第二次执行时速度减慢的一个主要原因。可能还有内核数据结构的数据缓存未命中,以跟踪内容 不过,惰性设置也是可能的 您可以

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

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


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

我猜,涉及的内核代码的指令缓存未命中是第一次到第二次执行时速度减慢的一个主要原因。可能还有内核数据结构的数据缓存未命中,以跟踪内容

不过,惰性设置也是可能的


您可以在两次试验之间(包括第一次试验之前)进行
睡眠(10)
测试。在每次试用之间,执行一些将使用所有CPU缓存的操作,例如刷新网页。如果是惰性设置,那么第一次调用将非常慢。如果没有,那么当缓存处于冷态时,所有调用都将同样缓慢。

在linux内核中,您可以找到
\uuuuuuu sys\u sendmsg
函数,该函数由
send
使用。选中查看代码

函数必须将用户消息(在您的例子中是8KB
buf
)从用户空间复制到内核空间。之后,
recv
可以将接收到的消息从内核空间复制回子进程的用户空间

这意味着一个send()recv()对需要2个memcpy和一个kmalloc

第一个非常特殊,因为没有分配存储用户消息的空间。这也意味着它也不存在于数据缓存中。因此,第一对
send()-recv()
将分配内核内存来存储
buf
,这也将被缓存。下面的调用将使用函数原型中的
used\u address
参数使用该内存


所以你的假设是正确的。第一次运行在内核中分配8KB并使用冷缓存,而其他运行只使用以前分配和缓存的数据。

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

如果您确实想要使用两个进程,那么您应该首先执行另一个方向的发送,以便父进程可以等待子进程准备就绪 开始发送

例如: 儿童:

家长:

  recv();
  gettime();
  send();
  recv();
  gettime();
您还需要认识到,您的测试在很大程度上取决于不同CPU内核上的进程布局,如果在同一个内核上运行,将导致任务切换

因此,我强烈建议您进行测量 使用单个进程。即使没有民意调查,也可以这样做 只要您保留适合套接字缓冲区的合理小块:

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

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

可能就是这样,也可能与计划程序中的计时有关。顺便说一句,在计算
struct timespec
差异时,您可能不想忘记
tv_sec
。当秒递增时,这看起来像一个大数字,你将负纳秒差格式化为
%lu
  send();
  recv();
  send();
  recv();
  gettime();
  send();
  recv();
  gettime();
gettime();
send();
recv();
gettime();