[Netty筆記一]ByteBuf(一)

[Netty筆記一]ByteBuf(一)

Netty的ByteBuf很複雜,需要慢慢學習,先從java.nio.ByteBuffer對比看起。

一 JAVA NIO的ByteBuffer

ByteBuffer是個抽象類,通過靜態方法allocate、allocateDirect分別分配heap buf和direct buf。HeapByteBuffer就是heap buf的具體實現類,DirectByteBuffer就是direct buf的具體實現類。而ByteBuffer繼承自Buffer抽象類,ByteBuffer起了個承上啓下的作用,分配具體類型的緩存,並對Buffer的功能進行復雜接口的封裝。

1. Buffer抽象類

Buffer定義了基本操作邏輯。主要操作:

1) mark()

使用變量mark來表示,用於標記當前位置。可能的用法場景:從某個位置開始操作,但是不滿足條件,需要回退。在這種場景下可以用mark()函數先標記其實位置,操作,不滿足條件時,用reset()回退到mark()標記的位置。

2) position

position變量用於標示當前操作所處的位置。讀寫兩個操作都用同一個變量position來指示當前操作的位置。沒錯,你沒看錯,是同一個變量來控制讀取和寫入。。。

3) flip()

​ flip操作,可以理解爲一個開關,用於控制讀寫轉換。如用put向緩存中寫入了3個字節,此時position=3,可讀取的字節爲3;調用flip後,position=0,limit=3,意味着從0開始,可以讀取3個字節。

4) limit和capacity

capacity就是緩存大小,一旦初始化,後續沒法動態調整;limit就是當前緩存的數據量。

5) rewind()

將position清0,mark變量清掉。使用場景與flip類似,前提是需要自己準確設定limit。

2. ByteBuffer

ByteBuffer除了提供緩存的靜態方法,還提供一下方法。

1) put() get()

put和get爲抽象方法,put用於寫入,get用於讀取,就是上面Buffer中提到的讀寫操作。

2) slice()

切片。就是從緩存當前位置切割,而使用剩下的數據。當然,這個是數據是共享的,只是通過調整位置來實現這一功能。不過要說明的是,ByteBuffer使用offset這個變量來實現這一功能,而不是直接通過調整position來實現,即position還是原有的定義,但是用offset來調整緩存的起始位置(ix()函數)。

3) duplicate()

複製。這個操作數據也是共享的,只是重新包裝了一下,也就是位置變量之類的不同。

3. 其它

從上面的介紹來看,JAVA NIO提供的ByteBuffer總體功能有限,尤其是讀寫轉換需要flip這個操作,使用起來會比較無力,對於複雜的讀寫操作,還需要自己牢記各種位置來mark,reset,rewind。。。

二 ByteBuf

Netty與NIO的緩存有比較大的區別,簡單概括如下:

1) 內部指針

上面提到NIO的Buffer使用一個position變量同時被讀寫操作使用,需要flip來轉換讀寫模式,同時mark也只有一個變量; Netty的ByteBuf則使用readerIndex、writerIndex,標記位也有兩個markedReaderIndex、markedWriterIndex,取消了limit,writerIndex就可以達成類似的作用;使用上最大的便利就是不需要flip來回轉換了:-)。。。

2) 組合模式

​ CompositeByteBuf可以將多個ByteBuf組合在一起,但是實現了ByteBuf接口。也就是當組合多個ByteBuf時,不需要額外拷貝,卻可以像使用ByteBuf一樣,這個在協議編解碼場景,尤其有用。這個也是NIO完全缺失的一個特性。

3) 池化

​ Netty提供了池化和非池化兩種方式來獲取ByteBuf實例。池化可以最大限度減少內存碎片,非池化與NIO方式一致,沒有爲內存管理做特殊處理。池化和非池化,與heap buf和direct buf是兩個概念,heap與direct是內存分配方式,池化是對分配的內存做管理。同樣,NIO也沒有這個特性。

4) 內存追蹤

​ Netty中有ReferenceCounted接口專門用於負責追蹤內存使用。retain方法增加引用計數,release方法減少引用計數。該功能主要是針對direct內存。

5) 工具類

​ Netty提供了豐富的工具類,用於場常見的字符串處理以及其它功能。如ByteBufUtil工具類,定義了很多的工具方法,最常用的應該是hexDump,對於調試打印非常方便;還有ByteProcessor接口類,在遍歷ByteBuf時也非常方便。

總結

剛開始接觸Netty的時候,只是好奇大家都在說的高性能,簡單的寫了個demo,除了pipeline,沒啥感覺(請原諒我的無知);直到看到了源碼中給出的示例,才發現Netty的牛逼,可以用非常簡單的代碼來實現一個代理功能,這種代碼實現上的優雅讓我折服,準備花時間把Netty系統學習一下。本文是第一篇,後面繼續。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章