Netty-内存池源码一 (内存分配入口)

Netty-内存池源码一 (内存分配入口)

当 Client 向 Server 发送请求, 此时Server端的 【NioSocketChannel】 则会响应 【readOps】 事件。而在处理该事件时, 需要使用ByteBuf , 那么目标就指向:

AbstractNioByteChannel #NioByteUnsafe # read()

public final void read() {

    //.....省略

    // #1. 获取  池化内存缓冲区分配器
    final ByteBufAllocator allocator = config.getAllocator();

    // #2. 获取  缓冲区大小预测器
    final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();

    ByteBuf byteBuf = null;
    boolean close = false;
    try {
        do {
            
            //#3. 分配出一块内存 byteBuf
            byteBuf = allocHandle.allocate(allocator);
           
        } while (allocHandle.continueReading());

    }  // .....省略
}

从代码看 allocator 就是 分配Netty 用来分配内存的大佬, 那么 该池化内存缓冲区分配器是谁?

  1. #1 final ByteBufAllocator allocator = config.getAllocator();

    跟随 config.getAllocator() 可知,该allocator 是由 【ByteBufUtil】工具类获取的,代码如下

    ByteBufAllocator allocator = ByteBufUtil.DEFAULT_ALLOCATOR;

    进入【ByteBufUtil】, 其中有段关键的代码

         
    	// 当前平台若是Android 内存分配器则使用 unpooled,  若不是则使用 pooled
    	String allocType = SystemPropertyUtil.get(
                    "io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");
    
    
            ByteBufAllocator alloc;
            if ("unpooled".equals(allocType)) {
                alloc = UnpooledByteBufAllocator.DEFAULT;
                logger.debug("-Dio.netty.allocator.type: {}", allocType);
            } else if ("pooled".equals(allocType)) {
                
                // 默认会使用 该内存分配器 PooledByteBufAllocator
                alloc = PooledByteBufAllocator.DEFAULT;
                logger.debug("-Dio.netty.allocator.type: {}", allocType);
            } else {
                alloc = PooledByteBufAllocator.DEFAULT;
                logger.debug("-Dio.netty.allocator.type: pooled (unknown: {})", allocType);
            }
    
            DEFAULT_ALLOCATOR = alloc;
    

    从上面代码可知, 默认普通情况下 内存分配器就是 【PooledByteBufAllocator

  2. #3 byteBuf = allocHandle.allocate(allocator); 下面跟踪该分配方法:

    => 1.【DefaultMaxMessagesRecvByteBufAllocator #MaxMessageHandle #allocate()】: alloc.ioBuffer(guess());

    => 2.【AbstractByteBufAllocator #ioBuffer()】: directBuffer(initialCapacity); 这里我们默认使用直接内存。

    => 3. 【AbstractByteBufAllocator #directBuffer()】:

    newDirectBuffer(initialCapacity, maxCapacity);

    => 4. 最终会来到 PooledByteBufAllocator #newDirectBuffer() 该方法就是申请分配内存的入口

posted @ 2021-12-15 22:20  s686编程传  阅读(147)  评论(0编辑  收藏  举报