【问题标题】:full cache linux cause drop at nic完全缓存 linux 导致 nic 掉线
【发布时间】:2022-01-19 14:31:55
【问题描述】:

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

所以有 32 个进程使用 dpdk 从 nic 接收流量,每个进程从不同的队列读取,从 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。

【问题讨论】:

  • 请添加代码 sn-p 以更好地了解应用程序和线程模型。也不清楚来自 NIC 的 rx_burst 是否会跟进写入磁盘中的数据。也请阅读如何提出好问题
  • @VipinVarghese 我更新了问题,希望现在很清楚。对不起,我不能把完整的代码放在这里
  • @davidboo 所描述的问题是由于磁盘内容未定期刷新而是由 vfs 保留页面 (4KB)。这会导致你的记忆力下降。 DPDK 使用大页面(在 x86 2MB 和 1GB 上)我谦虚地请求修复写入磁盘的问题(这不是 DPDK 问题)。
  • @VipinVarghese 我不明白这个提议,它在第一次下降前 2 小时运行。可用内存为 47 G。我需要做哪些不同的事情?
  • @davidboo 我没有提出任何建议。我指出了为什么你的disk content not flushed periodically but held page (4KB) by vfs,因为你正在写入磁盘,所以你能帮我改一下你的问题吗?

标签: dpdk mellanox


【解决方案1】:

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

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

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

  1. 函数 PullfromQueue
  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 页面或透明大页面上(希望从不设置)以提高性能。它看起来像 cmets 中的基于对话,因为缓存实际上 DISK IO 运行速度较慢,这导致 WriterThreadMainFunc 运行速度较慢。要按照 cmets 中的建议检查此行为,请

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

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

注意:还有许多其他选项,例如创建每个端口队列、每个流、每个流端口队列并使用 mmap 来满足当前要求。

【讨论】:

  • 我没有写所有的数据包,传递给写入线程的数据包在推送到队列之前被复制到内存中 dpdk-prociinfo 可以在我运行我的应用程序的同时运行吗?
  • 当前代码 sn-p shared 不共享数据包缓冲区是否被复制。也没有调用 tx_burst 或 mbuf_free。因此,我必须假设你也在做同样的事情。关于 proc_info 是的,只要您不使用 in memory 或仅用于 real_init 的主要选项,您就可以为您的应用程序运行
  • 1.我仍然不明白为什么在内存中缓存(这是操作系统的预期行为)会导致卡掉线。即使缓存的文件被写入磁盘。当进程请求它时,缓存内存是可用的。 2.即使对写入的文件的大部分进行fflush和fsync。一些文件读/写将被缓存到内存中,我将在 4 小时后而不是 2 小时后以 drop at nic 结束
  • 如 cmets 和答案中所述,当调用 TX 或 mbuf free 时,mbuf 会被补充到内存池中。而且你分享的代码sn-p是不完整的。我已经回答了为什么磁盘启动 4k 页面缓存构建以及如何避免它。还要求您检查建立的 rxnombuf 计数器(检查无法释放 mbuf 方案)。如果您准备好调试并分享计数器值以帮助您,我很高兴与您进行聊天或调试
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多