c语言 - 在内核 4.14 中发送带有'MSG_ZEROCOPY'标志和'SO_ZEROCOPY'选项的 bufs 的行为比 non_zerocpy 差



我尝试了内核 4.14 的zero_copy,以下是内核 4.14 中zero_copy的详细信息。

[1](https://netdevconf.org/2.1/papers/netdev.pdf(

我在鱿鱼中对其进行了测试,这是一个缓存代理。我的代码与上面略有不同。我使用 epoll 来处理零拷贝和复制磁盘文件以发送到客户端。当套接字可写时,我使用如下函数

send(fd, buf, sz, MSG_ZEROCOPY); //sz=16KB, 32KB

此外,我按如下方式处理 EPOLLERR 以释放分配的 buf。

recvmsg(fd, &msg, MSG_ERRQUEUE)

但是我发现 fd 经常被 EPOLLERR 唤醒,所以我在每次发送调用后都会调用 recvmsg,否则 CPU 运行得非常高。然后我使用 curl 向具有请求缓存的 squid 代理发出请求。

foreach -c 400 -w 4 'curl -o /dev/null -s -w "%{time_connect} %{time_total} %{speed_download}n" http://160MB.html -x 192.168.1.20:3128 -H "Pragma: "'

但结果表明,non_zero_copy代码更快。并且 cpu 热函数分布如下:

non_zero_copy: %Cpu1  : 21.9 us, 77.1 sy,  0.0 ni,  0.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.3 st 
   32.52%  [kernel]             [k] copy_user_enhanced_fast_string
   8.73%  libc-2.17.so         [.] __memcpy_ssse3_back
   6.36%  [kernel]             [k] iowrite16
   3.97%  [kernel]             [k] do_syscall_64
   3.60%  [kernel]             [k] _raw_spin_unlock_irqrestore
   3.25%  libc-2.17.so         [.] __memset_sse2
   2.74%  [kernel]             [k] find_get_entry
   2.03%  libpthread-2.17.so   [.] pthread_cond_wait@@GLIBC_2.3.2
   1.66%  [kernel]             [k] tcp_sendmsg_locked
   1.44%  [kernel]             [k] generic_file_read_iter
   0.84%  [kernel]             [k] finish_task_switch
   0.80%  libc-2.17.so         [.] epoll_ctl
   0.78%  [kernel]             [k] __fget
   0.78%  [kernel]             [k] get_page_from_freelist
   0.77%  [kernel]             [k] sock_poll
   0.71%  [kernel]             [k] skb_release_data
   0.69%  libpthread-2.17.so   [.] __pthread_disable_asynccancel
   0.64%  [kernel]             [k] sys_epoll_ctl
   0.62%  [kernel]             [k] __audit_syscall_exit
zero_copy: %Cpu1  : 35.8 us, 63.9 sy,  0.0 ni,  0.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
   9.41%  [kernel]             [k] do_syscall_64
   8.57%  [kernel]             [k] copy_user_enhanced_fast_string
   7.79%  [kernel]             [k] _raw_spin_unlock_irqrestore
   7.55%  libc-2.17.so         [.] 0x00000000000f7d13
   6.70%  [kernel]             [k] ep_send_events_proc
   5.11%  [vdso]               [.] __vdso_gettimeofday
   4.73%  libc-2.17.so         [.] __memset_sse2
   4.16%  [kernel]             [k] pvclock_clocksource_read
   3.66%  libc-2.17.so         [.] __memcpy_ssse3_back
   2.02%  [kernel]             [k] tcp_poll
   1.95%  [kernel]             [k] iowrite16
   1.93%  squid                [.] comm_select
   1.73%  [kernel]             [k] find_get_entry
   1.57%  [kernel]             [k] sock_poll
   1.54%  [kernel]             [k] __fget
   1.53%  [kernel]             [k] select_estimate_accuracy
   1.41%  squid                [.] getCurrentTime
   0.86%  [kernel]             [k] ktime_get_ts64
   0.84%  [kernel]             [k] ep_poll
   0.83%  [kernel]             [k] ep_scan_ready_list.isra.13
   0.81%  libpthread-2.17.so   [.] pthread_cond_wait@@GLIBC_2.3.2
   0.73%  [kernel]             [k] fput
   0.71%  [kernel]             [k] __audit_syscall_entry
   0.71%  [kernel]             [k] __audit_syscall_exit
   0.70%  [kernel]             [k] mutex_lock
   0.66%  [kernel]             [k] _raw_spin_lock_irqsave
   0.59%  libc-2.17.so         [.] __libc_disable_asynccancel
   0.57%  squid                [.] statHistCount

有人和我做同样的测试吗?以及为什么我的测试与上面 pdf 中的文章的结果不同。

您是否正在尝试通过环回或真实网卡进行零复制?请务必先检查文档/网络/msg_zerocopy.rst

回送

发送到本地套接字的数据可以无限期排队,如果接收 进程不读取其套接字。未绑定通知延迟不是 可以接受。因此,使用 MSG_ZEROCOPY 生成的所有数据包 循环到本地套接字将导致延迟副本。这 包括循环到数据包套接字(例如 TCPDUMP(和 tun 设备。

另外,查看实现,似乎您的网卡必须已启用tx-scatter-gather-fraglist。在ethtool -k中检查它。

   zc = sk->sk_route_caps & NETIF_F_SG;
    if (!zc)
      uarg->zerocopy = 0; 
enum {
  NETIF_F_SG_BIT,     /* Scatter/gather IO. */

我什么都不修改,只是将测试从虚拟机移动到真实机器:该功能__zerocopy_sg_from_iter从未在虚拟机中发生过,而是在真实机器中发生过。

ZERO_COPY: (in real machine)
%Cpu1  : 17.8 us, 34.9 sy,  0.0 ni, 47.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
13903 squid     20   0  147236  45196   5860 R  52.2  0.1   0:15.65 squid  
  18.42%  libc-2.17.so         [.] __memcpy_ssse3_back
  17.32%  [kernel]             [k] copy_user_generic_string
   2.79%  [kernel]             [k] syscall_return_via_sysret
   2.09%  [unknown]            [k] 0xfffffe800003201e
   1.91%  [kernel]             [k] gup_pgd_range
   1.21%  [kernel]             [k] generic_file_read_iter
   1.20%  [kernel]             [k] _raw_spin_lock
   1.05%  [kernel]             [k] sock_poll
   1.04%  [kernel]             [k] sys_epoll_ctl
   1.02%  [kernel]             [k] __schedule
   0.97%  [kernel]             [k] __audit_syscall_entry
   0.93%  [kernel]             [k] __zerocopy_sg_from_iter
and i make a comparisonwith NO_ZEROCOPY in real machine
%Cpu1  : 11.4 us, 46.8 sy,  0.0 ni, 41.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st                                                                                                                 
13988 squid     20   0  115948  15228   5784 R  57.5  0.0   0:31.99 squid
   33.27%  [kernel]             [k] copy_user_generic_string
   9.62%  libc-2.17.so         [.] __memcpy_ssse3_back
   2.34%  [kernel]             [k] syscall_return_via_sysret
   1.80%  [unknown]            [k] 0xfffffe800003201e
   1.35%  [kernel]             [k] tcp_sendmsg_locked
   1.18%  [kernel]             [k] generic_file_read_iter 
    NO_ZEROCOPY    ZERO_COPY
cpu 62.9           53.6
cpu 53.6           43.3
cpu 46.8           34.9

最新更新