mbuf多内存池

在DataFlow的内存分配场景中,mbuf是驱动对于内存管理的统一机制,所有的FlowMsg都会在mbuf池中进行生成并使用。每个FlowMsg都会申请一段mbuf内存:

1
2
3
sizeMbuf  = 
       sizeof(MbufData) // FlowMsg实际包含的内存大小
     + sizeof(MbufHead) // mbufHead大小,实际为1024B

考虑到内存不要过于频繁的进行申请,驱动对于不同大小的mbuf内存的使用有不同的限制:

可能的报错场景

考虑到用户存在大量UDF进程,且每个UDF进程都可能申请大量小内存场景,mbuf的申请释放可能存在以下场景:

当存在极端用例场景时:

  1. 在time1的时间点,存在多个大块内存(3G),与多个小块内存(2M)。
  2. 在time2的时间点上,大内存不再占用,可以释放掉。此时,从内存池整体状况来看,整体占用内存为:2M + 2M,可用内存为9G+。
  3. 此时,在time3的时间点上,因为存在内存碎片,无法申请5G内存。

mbuf多内存池

针对上述场景,考虑额外新增内存池配置,用以缓解该种内存碎片问题。主要方法是,将mbuf设置为可配置多内存池系统,小内存放入专用小内存池中。

mbuf多内存池示例图如下。

  1. 在time1的时间点,存在多个大块内存(3G),与多个小块内存(2M)。
  2. 在time2的时间点上,大内存不再占用,可以释放掉。此时,从内存池整体状况来看,整体占用内存为:2M + 2M,可用内存为9G+。
  3. 此时,在time3的时间点上,大内存池中内存重组,可以申请。

当前该方案是通过“ge.flowGraphMemMaxSize”实现的,该参数具体含义如下。

FlowGraph场景下,网络可使用的内存配置,可根据网络大小指定。单位:Byte,可以支持多个内存池配置,最多支持128个内存池,配置格式为"内存池1大小:申请内存限制,内存池2大小:内存申请限制,...,内存池n大小:内存申请限制", 如果不设置,默认单个内存池,大小10GB,申请内存大小不限制。

内存池大小取值最小1024,最大274877906944(256G),所有内存池大小加起来不能超过256G,实际使用时受芯片硬件限制。

申请内存限制取值范围为0或者[1024,2147483648(2GB)],为可选配置,默认为0,表示不限制。

典型配置示例:

1
{"ge.flowGraphMemMaxSize", "10737418240"} 

表示只有一个内存池大小为10G,申请内存大小不限制。

1
{"ge.flowGraphMemMaxSize", "10737418240,2147483648:2097152"} 

表示申请两个内存池,内存池1大小为10GB,申请内存大小不限制;内存池2大小为2GB,最大可以申请2M,申请内存时小于等于2M时会优先在2GB内存池中申请,大于2M的只能在10GB内存池中申请。

1
{"ge.flowGraphMemMaxSize", "10737418240,2147483648:20971520,1073741824:2097152"} 

表示申请三个内存池,内存池1大小为10GB,申请内存大小不限制;内存池2大小为2GB,最大可以申请20M;内存池3大小为1GB,最大可以申请2M,申请内存时会根据申请内存大小优先匹配对应的内存池,比如小于等于2M时会优先在1GB内存池中申请,大于2M小于等于20M的优先在2GB内存池中申请,大于20M的只能在10GB内存池中申请。