.net core中的System.Buffers名字空間


最近研究了一下.net core 2.1的基礎類庫,發現它引入了一個System.Buffers名字空間,里面提供了一系列比較實用的對象,便簡單的管中窺豹瀏覽一下。

 

ArrayPool<T>

ArrayPool<T>是一個數組類型的對象池,本身ArrayPoo<T>是一個抽象類,但他有一個默認的實現ArrayPoo<T>. Shared,使用方法如下:

var pool   = ArrayPool<byte>.Shared;
var buffer = pool.Rent(2048);
try
{
    //
使用buffer
}
finally
{
    pool.Return(buffer);
    //
歸還buffer后不要再使用
}

方法比較簡單:

  1. 通過Rent從對象池中申請buffer
  2. 使用完后,通過Return將buffer歸還至對象池

微軟的文檔上並沒有詳細描述默認的ArrayPoo<T>的對象申請算法,但由於其代碼是開源的,還是可以到github上看到其實現方式的。

初略的看了一下,貌似也並不復雜,和傳統的對象池的維護方式也差不多:

  1. 系統維持着一個對象池
  2. 調用Rent的時候,首先會到對象池中查看是否有合適的對象(至少要滿足最小長度),如果有則直接返回對象池中的對象,並將其從對象池中移除
  3. 調用Return時,將對象放置到對象池,從而可以作為下次Rent的候選對象

注:這里只記錄了主要相關功能,實際算法比這個復雜。另外由於沒有很詳細看實現方式,如要描述不正確的地方歡迎指正

也就是說,return后的對象,很可能被別的地方rent走,因此可能導致讀寫沖突。(類似於c語言中的野指針,但仍然是安全的,不會造成內存錯誤)

 

MemoryPool<T>

除了ArrayPool外,System.Buffers名字空間下還提供了一個MemoryPool,它的使用方式和ArraPool比較類似,基本示例如下:

var pool   = MemoryPool<byte>.Shared;
var buffer = pool.Rent(2048);
try
{
    var memory = buffer.Memory;
    //use Memory<byte>
}
finally
{
    buffer.Dispose();
}

整個過程還是非常類似的,不過釋放的時候是調用的Dispose方法,用起來實際要更加方便點。不過這里申請到的是Memory<T>對象,可能有的地方不像byte[]那樣適用 。

關於MemoryPool的實現,我在github上找了一下,還沒有看到。不過由於它返回的是Memory<T>,理論上來講應該是有更高的效率。(例如,可以把一個大段的buffer分成多個memory返回,從而減少申請新對象)

 

BinaryPrimitives

BinaryPrimitives位於System.Buffers.Binary名字空間下,它提供了一系列數字和字節互相轉換的函數。

  

它的主要好處是是提供了常用BigEndian類型的數字的支持,在網絡編程或者文件解析的方式的時候非常實用,免得造輪子了。

 

Utf8Parser、Utf8Formatter和Base64

這三個類位於System.Buffers.Text下,它主要用於utf8編碼和base64編碼下的常用類型的讀寫,如datetime,guid,bool等,並且支持常用的序列化方式。

這幾個類目前官方文檔都介紹的不是很詳細,目前要詳細了解的話只能看代碼。由於篇幅所限,這里也不做更多的介紹,以后用到的時候再寫單獨的文章介紹它們。

 

參考文章:

  1. ArrayPool<T> Class
  2. Pooling large arrays with ArrayPool


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM