1. 程式人生 > 其它 >Netty-記憶體池原始碼一 (記憶體分配入口)

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() 該方法就是申請分配記憶體的入口

萬般皆下品,唯有讀書高!