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