編寫高效能C#程式碼 —— Span<T>

颺大神發表於2023-11-07

Span 提供任意記憶體的連續區域的型別安全和記憶體安全表示形式。它是在堆疊而不是託管堆上分配的ref結構,是對任意記憶體塊的抽象 。

1.關於Span

  • 在NET Core 2.1中首次引入

  • 提供對任意記憶體上的連續區域的讀寫檢視

  • 利用索引/迭代來修改範圍內的記憶體
  • 幾乎無開銷

2.和記憶體的關係

   Span 表示任意記憶體的連續區域。 Span<T>例項通常用於儲存陣列的元素或陣列的一部分。 但是,與陣列不同, Span<T>例項可以指向堆疊上託管的記憶體、本機記憶體或託管的記憶體。

3.效能測試

  Span通常用來處理陣列,所以本次測試的場景是陣列的切分:從一個陣列的中間元素開始,獲取並返回四分之一個元素。

  3.1 陣列初始化

  這裡我們準備一個陣列分三種不同長度進行初始化,有利於覆蓋到更多的測試情況。

 

  3.2 測試採用三種方式,用BenchmarkDotNet比較一下

  第一種(常規):

   第二種(複製):

   第三種(Span切片):

   效能測試結果如下,可以看到Span的速度是很快的,且不佔記憶體。

 

 4. 切片

  Span<T>.Slice()方法就是對記憶體進行切片,第三種方法區別於前兩種,本質上不建立和銷燬物件,可以認為是做到了記憶體0分配

5. ReadOnlySpan

  ReadOnlySpan是Span的只讀表示形式,通常用在string的切片(因為string的不可變性)

 

 6. Span<T>侷限性

  1. Span是僅限存活在堆疊上的值型別

  2. Span不能是非堆疊型別的欄位

  3. Span不能被裝箱

  4. Span不能是非同步方法的引數或區域性變數

  5. Span不能被lambda表示式捕獲

相關文章