Flink内存管理源码解读之内存管理器

本文深入探讨Flink的内存管理机制,包括MemoryManager如何负责内存分配和回收,MemoryPool如何实现内存池,以及AbstractPagedXXXView如何支持跨segment的数据访问。重点介绍了MemoryManager的预分配策略、MemoryPool的双端队列实现以及AbstractPagedInputView和AbstractPagedOutputView的数据读写方法。
摘要由CSDN通过智能技术生成

回顾

上一篇文章我们谈了Flink自主内存管理的一些基础的数据结构。那篇中主要讲了数据结构的定义,这篇我们来看看那些数据结构的使用,以及内存的管理设计。

概述

这篇文章我们主要探讨Flink的内存管理类MemoryManager涉及到对内存的分配、回收,以及针对预分配内存而提供的memory segment pool。还有支持跨越多个memory segment数据访问的page view。

本文探讨的类主要位于pageckage : org.apache.flink.runtime.memory下。完整类图:

flink-source-code-analysis-memory-management-1_all-class-diagram

MemoryManager

MemoryManager 作为Flink的内存管理器,承担着MemorySegment的分配、回收等职责。

为了提升MemorySegment的复用能力,它提供了不同memory type的MemorySegment池的实现,它们是:

  • HeapMemoryPool
  • HybirdOffHeapMemoryPool

首先,这里为了提升memory segment操作效率,MemoryManager鼓励长度相等的memory segment。由此引入了page的概念。其实page跟memory segment没有本质上的区别,只不过是为了体现memory segment被分配为均等大小的内存空间而引入的。可以将这个类比于操作系统的页式内存分配,page这里看着同等大小的block即可。MemoryManager提供的默认page size为32KB,并提供了自定义page size的下界值不得小于4KB。

    /** The default memory page size. Currently set to 32 KiBytes. */
    public static final int DEFAULT_PAGE_SIZE = 32 * 1024;

    /** The minimal memory page size. Currently set to 4 KiBytes. */
    public static final int MIN_PAGE_SIZE = 4 * 1024;

MemoryManager允许自定义page size,它提供的构造器可以指定这个参数,一个MemoryManager应对一个page size,而且指定了就不允许改变。

page化的segment跟非page化的segment:

flink-source-code-analysis-memory-management-1_page-and-non-page

将segment page化会给后面的跨多个segment的访问带来更高的效率。

MemoryManager这个类本身没有特别的地方,并可能会被跨线程共享。这时某些操作可能会牵扯到多线程的并发问题。因此,MemoryManager提供了一个对象作为锁,以在某些方法上进行同步操作。

    /** The lock used on the shared structures. */
    private final Object lock = new Object();

两个构造器:

    public MemoryManager(long memorySize, int numberOfSlots) {
  
    public MemoryManager(long memorySize, int numberOfSlots, int pageSize, MemoryType memoryType, boolean preAllocateMemory) {
  

第一个构造器内部调用了第二个构造器,并用DEFAULT_PAGE_SIZE作为pageSize,HEAP作为memory type。

需要提及一下的是,这里的参数numberOfSlots 是跟Flink的task manager相关,暂时不做过多介绍,等到我们讲解Flink runtime时再细说。

第二个构造器的另一个参数preAllocateMemory,指定memory manager的内存分配策略是预分配还是按需分配。我们后面会看到,对于这两种策略,相关的内存申请和释放操作是不同的。

第二个构造器内就已经根据memory type将特定的memory pool对象初始化好了:

        switch (memoryType) {
            case HEAP:
                this.memoryPool = new HeapMemoryPool(memToAllocate, pageSize);
                break;
            case OFF_HEAP:
                this.memoryPool = new HybridOffHeapMemoryPool(memToAllocate, pageSize);
                
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值