flink网络缓冲池

本文深入解析Flink网络缓冲池NetworkBufferPool的工作原理。详细介绍了构造方法如何根据申请的MemorySegment数量和大小初始化内存缓冲池,以及createBufferPool()方法如何在LocalBufferPool间动态分配和调整内存资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flink的网络缓冲池NetworkBufferPool。

构造方法需要两个参数,申请的MemorySegment个数和单个MemorySegment的大小,两者乘积是整个内存缓冲池的总容量。

内部存储结构是一个队列,未分配的MemorySegment存储在队列当中,当被分配时会从内存中取出。

try {
   this.availableMemorySegments = new ArrayBlockingQueue<>(numberOfSegmentsToAllocate);
}
catch (OutOfMemoryError err) {
   throw new OutOfMemoryError("Could not allocate buffer queue of length "
         + numberOfSegmentsToAllocate + " - " + err.getMessage());
}

try {
   for (int i = 0; i < numberOfSegmentsToAllocate; i++) {
      availableMemorySegments.add(MemorySegmentFactory.allocateUnpooledOffHeapMemory(segmentSize, null));
   }
}

以上是其构造方法中的主要部分。

 

NetworkBufferPool提供了createBufferPool()方法可以申请本地缓冲池。

this.numTotalRequiredBuffers += numRequiredBuffers;

// We are good to go, create a new buffer pool and redistribute
// non-fixed size buffers.
LocalBufferPool localBufferPool =
   new LocalBufferPool(this, numRequiredBuffers, maxUsedBuffers, owner);

allBufferPools.add(localBufferPool);

需要提供申请的MemorySegment数量和最大使用MemorySegment数量,这些参数也将作为LocalBufferPool的构造方法参数,之后将其存放在去Set中便于管理。

在建立完毕LocalBufferPool并放入容器当中之后会在createBufferPool()方法中通过redistributeBuffers()方法重新分配网络缓冲池中的内存分配。

final int numAvailableMemorySegment = totalNumberOfMemorySegments - numTotalRequiredBuffers;

if (numAvailableMemorySegment == 0) {
   // in this case, we need to redistribute buffers so that every pool gets its minimum
   for (LocalBufferPool bufferPool : allBufferPools) {
      bufferPool.setNumBuffers(bufferPool.getNumberOfRequiredMemorySegments());
   }
   return;
}

如果当前,网络缓冲池中的内存正巧耗尽 ,那么将LocalBufferPool容器中的LocalBufferPool中的内存数量全部设为最小并返回。

long totalCapacity = 0; // long to avoid int overflow

for (LocalBufferPool bufferPool : allBufferPools) {
   int excessMax = bufferPool.getMaxNumberOfMemorySegments() -
      bufferPool.getNumberOfRequiredMemorySegments();
   totalCapacity += Math.min(numAvailableMemorySegment, excessMax);
}

// no capacity to receive additional buffers?
if (totalCapacity == 0) {
   return; // necessary to avoid div by zero when nothing to re-distribute
}

之后遍历容器,依次计算剩余容量和 单个容器距离最大容量的差的 最小值之和为totalCapacity,为理想情况下每个LocalBufferPool可分配到的内存总量。

final int memorySegmentsToDistribute = MathUtils.checkedDownCast(
      Math.min(numAvailableMemorySegment, totalCapacity));

long totalPartsUsed = 0; // of totalCapacity
int numDistributedMemorySegment = 0;
for (LocalBufferPool bufferPool : allBufferPools) {
   int excessMax = bufferPool.getMaxNumberOfMemorySegments() -
      bufferPool.getNumberOfRequiredMemorySegments();

   // shortcut
   if (excessMax == 0) {
      continue;
   }

   totalPartsUsed += Math.min(numAvailableMemorySegment, excessMax);

   // avoid remaining buffers by looking at the total capacity that should have been
   // re-distributed up until here
   // the downcast will always succeed, because both arguments of the subtraction are in the 'int' domain
   final int mySize = MathUtils.checkedDownCast(
         memorySegmentsToDistribute * totalPartsUsed / totalCapacity - numDistributedMemorySegment);

   numDistributedMemorySegment += mySize;
   bufferPool.setNumBuffers(bufferPool.getNumberOfRequiredMemorySegments() + mySize);
}

之后如上,剩余的容量numAvailableMemorySegment和剩余达到最大容量的差totalCapacity两者中的小者也正是接下来需要分配的内存总量。

接下来的LocalBufferPool可多分配的内存量为单 个LocalBufferPool理想可分配内存 占 总理想分配 的比乘上 总可分配内存 最后减去已分配的内存的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值