0

我有一个 dpdk 19 应用程序,并从 nic(MT27800 Family [ConnectX-5] 100G) 读取 32 rx multiqueue with RSS 。

所以有 32 个进程使用 dpdk 从 nic 接收流量,每个进程从不同的 Queue 读取,从 mbuf 复制数据到分配的内存,累积到 6MB 并通过无锁队列发送到另一个线程,其他线程只写数据到磁盘。结果 I/O 写入缓存在 linux 内存中。

所有进程都以cpu亲和力运行,grub中有isolcpus

这是从队列中读取的 32 个进程中的每一个中发生的一些伪代码,我不能放真正的代码,它太多了

MainFunction()
{
   char * local_buf = new...
   int nBufs = rte_eth_rx_burst(pi_nPort, pi_nQNumber, m_mbufs, 216);
   for(mbuf in m_mbufs)
   { 
       memcpy(local_buf+offset, GetData(mbuf),len);//accumulate to buf
       if(local_buf.len > MAX)
       {
          PushToQueue(local_buf);
          local_buf = new ...
       }
       rte_pktmbuf_free(mbuf);
   }
}

WriterThreadMainFunc
{
     While(QueueNotEmpty)      
     {
          buf = PullFromQ
          WriteToDisk(buf)
          delete buf;
     }

}

当服务器内存完全缓存时(我知道它仍然可用),我开始看到 nic 下降。

如果我每分钟从磁盘中删除数据,缓存的内存就会被释放,并且在 nic 上不会丢失。因此,水滴显然与缓存的数据相关联。在第一次下降之前,应用程序可以在没有下降的情况下运行 2 小时。该进程不使用太多内存,每个进程为 500 MB。

我怎样才能避免在 nic 滴水?

               total        used        free      shared  buff/cache   available
Mem:           125G         77G        325M         29M         47G         47G
Swap:          8.0G        256K        8.0G

我使用 Centos 9.7 linux 3.10.0-1160.49.1.el7.x86_64。

4

1 回答 1

0

DPDK APIrte_eth_rx_burst使用 mempool(或 pktmbuf)内存区域来保存元数据和以太网帧。在内部的每个 rx_burst 周期中

  1. 它检查本地缓存的 mempool 对象,从物理 NIC 获取 pkt_mbuf 到 DMA
  2. 如果未找到本地缓存mbuf,则获取mempool锁并从mempool中获取mbuf。
  3. 所有 mbuf 都标有ref_cntas 1,表示 mbuf 正在使用而不是释放。
  4. 除非 atx_burst or rte_mbuf_free被调用,否则 mbuf 永远不会被推送到本地缓存或内存池以供重用。

因此,正如代码片段中所共享的那样,性能WriterThreadMainFunc会影响内存池的可用性。也就是说,如果 rx_burst (Million Packet per Sec) 的速度大于

  1. 函数拉取队列
  2. 或函数 WriteToDisk
  3. 或两个功能

这将导致这种情况mbuf_free is slower than rx_burst。为了验证相同,可以

  1. dpdk-prociinfo for stats and xstats, 检查计数器rx_no_mbuf
  2. 或集成get_stats and get_xstats到同一个柜台。

通常文件在打开时(尤其是在 RW 模式下)将被缓存在 4k 页面或透明大页面上(期望从不设置)以提高性能。它看起来像评论中的基于对话,因为缓存实际上DISK IO运行速度较慢,这导致WriterThreadMainFunc运行速度较慢。要按照评论中的建议检查此行为,请

  1. 使用echo 1 | sudo tee /proc/sys/vm/drop_caches.
  2. 尝试fflush & fsync定期使用。
  3. 或创建 ramdisk 并打开文件以在 ramdisk 上读写。

一旦问题被隔离,您可以使用setbuf(f, NULL)在开始时禁用缓冲。

注意:还有许多其他选项,例如为每个端口队列、每个流、每个流端口队列创建带有 mmap 的当前要求。

于 2022-01-26T14:10:51.817 回答