C Span 原始碼解讀和應用實踐

2021-10-25 09:38:05 字數 2934 閱讀 5352

string 對 span / readonlyspan 的支援

public sealed class string

stringbuilder 對 span / readonlyspan 的支援

public sealed class stringbuilder : iserializable

}return this;

}}

int 對 span / readonlyspan 的支援

public readonly struct int32

}

怎麼樣,這些通用 & 基礎的類都在大力對接 span / readonlyspan,更別說複雜型別了,其地位不言自明哈,接下來我們就從 span 本身的機制聊起。

二: span 原理**

span 原始碼分析

靈活運用 span 解決工作中的實際問題我相信大家應該沒什麼毛病了,有了這個基礎再從 span 的原始碼 和 使用者態 和大家一起深度剖析,從原始碼開始吧。

public readonly ref struct span

; var span = new span(nums);

console.readline();

}接下來我用 windbg 把執行緒棧中的 span 也找出來。

0:000> dp 0x000001e956b8ab20

000001e956b8ab20 0000000200000001 0000000400000003 000001e956b8ab30 0000000600000005 0000000000000000

000001e956b8ab40 00007ffc3e6c4388 00000000`00000000

從上面三行記憶體位址來看,陣列的:1,2,3,4,5,6 依次排列,有些朋友可能有點小疑問,為啥 nums 的記憶體位址不是指向陣列元素 1 的呢? 那我來普及一下吧,先用 dp 喚出陣列的記憶體位址。

0:000> dp 0x000001e956b8ab10

000001e956b8ab10 00007ffc3e69f090 0000000000000006 000001e956b8ab20 0000000200000001 0000000400000003

000001e956b8ab30 0000000600000005 00000000`00000000

可以看出,第一排為: 00007ffc3e69f090 0000000000000006, 前面的 8 byte 表示 陣列 的 方法表位址,後面的 8byte 表示 6 ,也就是說陣列有 6個元素,不信的話我截一張圖:

span 是由 _pointer + length 組成的,剛才的 _pointer 也給大家演示了,那 length 的值在**呢? 因為 span 是 struct,所以需要用 dp 把剛才的執行緒棧最小的棧位址打出來就可以了。

到這裡,我覺得我講的已經夠清楚了,如果還有點懵的話可以仔細想一想哈。

在 string 上的應用

案例:如何高效的計算出使用者輸入的值 10+20 ?

傳統 substring 做法

傳統的做法很簡單,擷取唄,**如下:

static void main(string args)

+=");

console.readline();

}

結果是很輕鬆的算出來了,但你仔細想想這裡是不是有點什麼問題,比如說為了從 word 中扣出 num,我用了兩次 substring,就意味著會在 託管堆 上生成兩個 string,如果說我執行 1w 次話,那託管堆上會不會有 2w 個 string 呢? 修改**如下:

for (int i = 0; i < 10000; i++)

然後看一下 託管堆 上 string 的個數

0:000> !dumpheap -type string -stat

statistics:

mt count totalsize class name

00007ffc53a81e18 20167 556538 system.string

託管堆上有 20167 個,挺恐怖的,真的是給 gc 添麻煩哈,這裡還有 167 個是系統自帶的,接下來的問題是有沒有辦法替換 substring 從而不生成臨時string呢?

新式 span 做法

如果看懂了 span 結構圖,你就應該會使用 _pointer + length 將 string 進行切片處理,對不對,**如下:

for (int i = 0; i < 10000; i++)

然後在 託管堆 驗證一下,是不是沒有 臨時 string 了?

0:000> !dumpheap -type string -stat

statistics:

mt count totalsize class name

00007ffc53a51e18 167 36538 system.string

可以看到就只有 167 個系統字串,效能也得到了不小的提公升,???。

在 list 上的應用

平時用 span 的時候,更多的會應用到 array 上面,畢竟 array 在託管堆上是連續記憶體,方便 span 在上面畫乙個可視視窗,其實不僅僅是 array,從 .net5 開始在 list 上畫乙個檢視也是可以的,截圖如下:

因為 list 的 curd 會導致底層的 array 忽長忽短或重新分配,也就無法實現物理上的連續記憶體,所以 span 應用到 list 之後,希望list是不可變的,這也是官方的建議。

C Span 原始碼解讀和應用實踐

public sealed class string public sealed class stringbuilder iserializable return this public readonly struct int32 怎麼樣,這些通用 基礎的類都在大力對接span readonlysp...

openTLD 原始碼解讀

首先是run tld 在其次就是tldexample 最後到了初始化函式tldinit 第乙個比較關鍵的函式 bb scan 將影象網格化,將首先 scale 1.2.10 10 21 個規格 在每個規格上打網格 這個函式有乙個比較重要的方法 ntuples 就是重複 因為網格上的點很多點有相同的x...

thinkphp原始碼解讀

thinkphp原始碼解讀 thinkphp原始碼的根目錄下是 index.php,是系統預設的 主頁,index.php中首先檢測的是 php執行環境,如果php版本小於 5.3.0則退出執行,定義是否為除錯模式,定義應用目錄,引入入口檔案。thinkphp是整個框架的入口檔案,在thinkphp...