日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bytebuf池_Netty默认的Bytebuf是堆内还是堆外?池化or非池化?

發布時間:2025/3/12 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bytebuf池_Netty默认的Bytebuf是堆内还是堆外?池化or非池化? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

開篇

Netty的ByteBuf有從不同角度有如下2個分類,4種組合!

堆外內存和堆內內存

池化和非池化

我們在利用Netty做底層通信框架的時候,會默認給我們的到底是哪一種組合了?

分析

池化分析

Netty的Boostrap啟動類按照標準模板,通常會添加這個配置option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)

val serverBootstrap = ServerBootstrap().group(bossGroup, workGroup)

.channel(NioServerSocketChannel::class.java) //配置客戶端的channel類型 .option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)

//.....

那么通過默認的ByteBufAllocator.DEFAULT分配出來的是哪一種組合了?我們來通過代碼分析。

首先看看這個ByteBufAllocator.DEFAULT創建了一個什么類

public interface ByteBufAllocator {

ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR;

}

繼續調用下去,下述代碼省略了一些無關的細節!

public final class ByteBufUtil {

static final ByteBufAllocator DEFAULT_ALLOCATOR;

static {

//核心語句 String allocType = SystemPropertyUtil.get(

"io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");

allocType = allocType.toLowerCase(Locale.US).trim();

ByteBufAllocator alloc;

if ("unpooled".equals(allocType)) {

alloc = UnpooledByteBufAllocator.DEFAULT;

} else if ("pooled".equals(allocType)) {

alloc = PooledByteBufAllocator.DEFAULT;

} else {

alloc = PooledByteBufAllocator.DEFAULT;

}

//這里賦值了噢... DEFAULT_ALLOCATOR = alloc;

}

上述代碼最為核心的一句是:

String allocType = SystemPropertyUtil.get(

"io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled")

其表達的意思是

從系統配置(通常是啟動的命令行給的)中讀取io.netty.allocator.type,如果能夠讀取到,那么按照配置設置。但是這個參數我們通常是沒有設置的,所以會進行第二步判定

當讀取不到的情況下,又進行了一個判定:PlatformDependent.isAndroid(),當Netty運行在Android的時候是unpooled,否則是pooled

后面的代碼就是根據pooled和unpooled來進行對象初始化了。

綜上,我們大多數時候啟動參數都是沒有加對應配置的,且運行在非安卓的系統,所以是pooled的ByteBuf

堆外/堆外

接下來還需要確定默認情況下分配的ByteBuf是分配到堆內還是堆外的,從PooledByteBufAllocator.DEFAULT;點進去可以看到這個代碼

public static final PooledByteBufAllocator DEFAULT =

new PooledByteBufAllocator(PlatformDependent.directBufferPreferred());

這個構造函數的參數directBufferPreferred的中文意思不就是偏向堆外內存嗎?不過按照傳統這個應該是一個boolean的變量,猜測了這些,我們繼續看經過省略的源碼PlatformDependent。

public final class PlatformDependent {

private static final boolean DIRECT_BUFFER_PREFERRED;

static {

if (!isAndroid()) {

if (javaVersion() >= 9) {

CLEANER = CleanerJava9.isSupported() ? new CleanerJava9() : NOOP;

} else {

CLEANER = CleanerJava6.isSupported() ? new CleanerJava6() : NOOP;

}

} else {

CLEANER = NOOP;

}

DIRECT_BUFFER_PREFERRED = CLEANER != NOOP && !SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false);

}

核心的參數DIRECT_BUFFER_PREFERRED要想為true必須經過2步:

通過判定獲取CLEANER,這個判定牽扯到了另外的判定,這里就不貼代碼了,意思應該就是有沒有堆外內存的清理辦法,Java7+應該都有的

然后判定系統參數io.netty.noPreferDirect是不是為false

通常Java后端的系統這2個條件都是滿足的,所以恭喜:DIRECT_BUFFER_PREFERRED為true,堆外內存。

優劣

通過上面分析,我們知道了Netty默認的ByteBuf是堆外的池化模式,那么池化與否和堆外與否各自的優劣在哪里!?

通常池化意味者可以復用資源,減少系統資源的開銷

堆外內存可以使用更多可用的空間,畢竟Java虛擬機的大小一般都要小于系統的大小。但是江湖傳言堆外內存的開辟比堆內內存的開辟慢,這一點我不太能理解,這里記錄下。

以下是我在發文后的第二天從java.nio.ByteBuffer看到的文檔注釋!

A direct byte buffer may be created by invoking the {@link #allocateDirect(int) allocateDirect} factory method of this class. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers.

上文的意思翻譯下就是

堆外內存的創建可以通過調用allocateDirect這個工廠方法來創建。通過這個方法創建的buffer通常來說會比非堆外內存有更高的創建和釋放成本。

這里我還是納悶啊!**不是說C的效率要高于Java嗎?為什么堆外內存的創建和釋放會比堆內內存的成本更高了?**有知道的大佬嗎?

結語

本篇文章主要通過啟動參數的配置,進行了源碼分析,確認了Netty的ByteBuf使用的是堆外的池外模式。

騏驥一躍,不能十步。駑馬十駕,功在不舍。

總結

以上是生活随笔為你收集整理的bytebuf池_Netty默认的Bytebuf是堆内还是堆外?池化or非池化?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。