Netty-Buffer類都集中在io.netty.buffer的package中,主要功能是在數據傳輸時保存傳輸的數據,同時對通訊數據進行功能封裝,便於對數據空間進行管理。注:在其餘的package中有一些繼承自buffer的類,不在這裏說明。java
package以下:數組
HeapByteBuf是用byte數組格式來存儲數據,DirectByteBuf是使用java.nio.ByteBuffer來存儲數據。緩存
DirectByteBuf利用java.nio.ByteBuffer是藉助於JVM調用操做系統的底層通訊函數,直接操做直接緩衝區能夠減小中間緩衝區的複製操做,進而提供程序性能。網絡
HeapByteBuf是在JVM內部開闢緩衝區,在數據操做前先把數據複製到byte數組再進行處理。由於中間增長了一層數據複製操做,因此會影響性能。app
空間分配工具類:PooledByteBufAllocator和UnpooledByteBufAllocator,其中UnpooledByteBufAllocator在外又封裝了一個類Unpooled。ide
在緩存方式的分配類中,預申請了8個16K空間(分別是byte數組和java.nio.ByteBuffer)放在緩存中,經過相似工廠的建立函數建立ByteBuf時,先檢查緩存中的空間是否符合要求,若是符合先從緩存中分配空間,不然申請新的空間。函數
空間申請時判斷爲:大於chunkSize(16K),大於PageSize(8192)小於chunkSize(16K),小於PageSize大於512,小於512幾個檔。工具
注:這幾個值會根據操做系統的不一樣有所調整,以上值是在win7x64系統上的值。性能
①緩存方式測試
a、分配
根據構建是傳入參數的初始化空間,從對應的緩存空間中取得byte[],分配給到ByteBuf中memory變量。
b、擴展
在須要擴展的空間時,從緩存中取出一個符合要求的新的空間,即byte數組,把新申請的byte數組替換到ByteBuf中,執行System.arraycopy(src, srcOffset, dst, dstOffset, length);便可
②非緩存方式
a、分配
new一個byte[]賦值到ByteBuf的memory中,長度是傳入的初始化長度參數。
b、擴展
new一個新長度的byte[],替換ByteBuf中舊的memory,而後執行System.arraycopy(src, srcOffset, dst, dstOffset, length);便可
①緩存方式
a、分配
根據入口的初始化大小參數從緩存中取得對應的空間區域進行分配。
b、擴展
根據申請空間的要求,從緩存中取得(緩存中沒法知足時new一個java.nio.ByteBuffer)知足要求的java.nio.ByteBuffer,替換掉原有的java.nio.ByteBuffer,若是系統判斷爲unSafe時,直接複製舊的數據到新的java.nio.ByteBuffer;若是系統判斷不爲unSafe時,說明舊的數據還可能有其餘Buffer訪問,因此新舊java.nio.ByteBuffer同時進行自身複製一個新的java.nio.ByteBuffer,而後進行數據複製。
②非緩存方式
a、分配
new一個java.nio.ByteBuffer複製給ByteBuf的memory變量,長度爲入口的初始化大小參數。
b、擴展
new一個新的java.nio.ByteBuffer複製給ByteBuf的memory變量,而後把數據複製到新的java.nio.ByteBuffer中。
是一個虛擬的ByteBuf,在內部用List保存多個ByteBuf,而後虛擬爲一個ByteBuf供使用。應用場景未知。
同類型:FixedCompositeByteBuf,List長度爲固定長度
只讀ByteBuf。包括:ReadOnlyByteBuf、ReadOnlyByteBufferBuf、ReadOnlyUnsafeDirectByteBuf等
不建議直接構造此類ByteBuf。執行ByteBuf內部duplicate()生成一個自己的副本。
未知
SimpleLeakAwareByteBuf
反轉字序的ByteBuf
分片的ByteBuf,經過ByteBuf的slice()方法返回,和調用者共享從position指針到limit指針的這部份內容。
在服務端和客戶端通訊時,先把ByteBuf的capacity初始化爲1024,而後在接收數據的過程當中,再根據每次接收到的數據長度,猜想(動態計算)下次傳輸可能的數據長度,而後記錄這個長度,當下一次數據開始傳輸時把這個長度當作初始長度生成ByteBuf。而後依次循環使用,直到鏈接關閉爲止。
非緩存方式ByteBuf生成工具類,是ByteBufAllocator的一種簡單實現,生成的方式是每次調用都new一個新的ByteBuf。
提供了各類ByteBuf的實現方法。
緩存方式的ByteBuf生成工具類。預生成了一個高性能的buffer池,分配策略則是結合了buddy allocation和slab allocation的jemalloc變種。
這是官方推薦的工具類,因爲在先前的測試中可能存在內存泄露的現象,因此在鏈接初始化時使用的UnpooledByteBufAllocator分配ByteBuf。可是在官方的最新公告中表示已經解決了此問題,之後仍是推薦使用PooledByteBufAllocator來生成ByteBuf來提供總體性能。
ByteBuf空間分配核心類。提供了allocate()方法來初始化ByteBuf空間,以及reallocate()方法來動態擴容空間。
同時在繼承類HeapArena和DirectArena類中提供了memoryCopy()函數的空間擴容的具體實現。
ByteBuf的生成不建議直接使用new一個具體類的方式來實現,netty提供了生成工具類PooledByteBufAllocator和UnpooledByteBufAllocator供用戶使用。
無參數時是返回buf現有的容量;
有參數時是從新設置buf的容量,通常用於寫入時容量不足的狀況下進行擴容操做
無參數時返回buf的字節序
有參數時設置buf的字節序,同時依照新的字節序進行轉換
readableBytes()返回當前可讀的字節數:從readIndex到結尾的字節數。通常用於讀取數據前進行數據完整性的判斷。
readBytes()讀取數據到指定的obj變量中(還有其餘參數)。
writableBytes()是返回當前capacity可寫入的字節數是多少;
maxWritableBytes()是返回ByteBuf建立時的maxCapacity可寫入的字節數是多少
markReaderIndex()把當前的readerIndex賦值到markReaderIndex中。
resetReaderIndex()重設readerIndex,把markIndex賦值到readerIndex。
這兩個方法和readableBytes()、readBytes()結合使用能夠完成數據的讀取操做。
markWriterIndex()方法是把當前writeIndex賦值到markWriteIndex中。
resetWriterIndex()是把writeIndex設置爲markWriteIndex的值。
寫數據函數,把數據吸入到ByteBuf中。
通常在寫數據時和markWriterIndex()和resetWriterIndex()結合使用
清空ByteBuf,同時把readerIndex、markReaderIndex、writeIndex、markWriteIndex等設置爲0
在java.nio.ByteBuffer有capacity、position、limit、mark四種概念,除了容量不會改變之外,position、limit和mark在讀寫時都會發生改變,而且在讀操做前要調用flip()方法重設position和limit才能夠正確讀出寫入的數據。
而在netty的ByteBuf中,封裝時從新定義了readerIndex和writeIndex,在讀寫時只是操做對應的標誌位,開發者在使用當中讀寫時不用關心position、limit、mark,也不用執行flip()方法就能夠很方便的讀寫操做。
java.nio.Bytebuffer讀寫實例:
ByteBuffer buf = ByteBuffer.allocate(10);
buf.put(xxx);//寫完畢轉讀取時
buf.flip();//必須調用,不然讀取的數據不正確
buf.get(xxx);
而使用netty的ByteBuf時不須要關心這些指針,如:
ByteBuf buf = xxx;//生成新的ByteBuf
byte writeData[] = {...};
buf.writeBytes(writeData);//寫入數據
byte readData[] = new byte[11];
buf.readBytes(readData);//不用其餘操做,可直接讀取
經過上面的示例能夠看出,netty的ByteBuf使用起來更方便
HeapByteBuf由Heap管理,Heap是Java堆的意思,內部實現直接採用byte數組;DirectByteBuf使用是堆外內存,Direct應是採用Direct I/O之意,內部實現使用java.nio.DirectByteBuffer。
注:HeapByteBuf經過
在使用上的選擇:
場景1:網絡間的通訊:
A計算機的netty進程A1和B計算機上的netty進程A2進行通訊,這個時候涉及到跨網絡通訊的數據傳輸,前面說過DirectByteBuf是JVM直接操做操做系統的直接緩衝區可以×××能,那麼此時使用DirectByteBuf有利於提升程序性能,減小資源的使用。若是此時使用HeapByteBuf,那麼進程如今JVM內部分配緩衝區,寫完數據後再賦值到操做系統的直接緩衝區,而後進行網絡傳輸,這樣緩衝區的複製會影響性能,同時使用完畢後操做系統和JVM都要回收緩衝區資源,實際上增長了資源的使用,也下降了程序的性能。
場景2:進程內部的通訊:
同一臺計算機上的netty進程內進行通訊,這個時候只涉及到了進程內的通訊、涉及不到網絡間傳輸,這個時候使用HeapByteBuf會有更好的優點。
其餘;