文章出處

  我記得以前在園子里面討論這兩個類的文章有很多很多,并且還拿出了很多的測試報告,在什么情況下,誰比誰快,在什么情況下,該用誰

不該用誰等等這些,我這里就不比較了,我就簡單看看他們里面的內部實現,那就先看看String吧。

 

一:String類

  說到String類,資料上都說是存在于堆上的一個不可CURD的一個不可變的字符集,當然看到這句話之后就想要看看是不是這樣的,然后就

好奇的寫了以下代碼。

1     class Program
2     {
3         static void Main(string[] args)
4         {
5             string s = "123";
6         }
7     }

 

從上面的IL中也就僅僅發現一個ldstr指令,看得出clr把string做成了基元類型,也就沒看到它具體轉換成了什么樣的方法,是不是調用了string

的構造函數,這個也不清楚,也就不知道具體怎么把這個有序字符集放到堆中,不過辦法還是有的,我們隨便挑一個方法看看,比如簡單一點的

substring,我們看看它的源代碼。

 

 

然后我們找到了一個核心的方法,這個internalSubstring里面定義了兩個指針ptr和ptr2,ptr則指向新申請的內存塊的首地址,ptr2則指向原始

字符串的首地址,最后將ptr2的位置偏移startindex個位置,最后我們就找到了終極方法string.wstrcpy。

 

在string.wstrcpy方法里面,雖然看的迷迷糊糊,不過還是能看到類似這樣的偏移操作,一點一點的將smem地址上的字符賦值給dmem中,

確實也就說明了在堆上是有序的字符集。

 

 

同樣在上面的源代碼中來說,substring操作并沒有對原始字符串進行修改,而是把截取的值放到新申請的內存地址空間中,這也就說明了字符

串是不可修改的說法,當然如果設計者真的要做到原位修改,那肯定也是能做到的,為了佐證下,我再舉一個經常用到的concat方法,不過在

FastAllocateString方法中,并沒有看到他的源代碼,所以只能說根據length申請合適的空間。

 

所以結論出來了: 當你對字符串進行大量操作的時候,會產生很多的新的字符串,這些字符串會大量零碎的占據著堆空間,大多都是生存期較短

        的,所以一般都是在堆的第一代上,所以會對gc產生了比較大回收壓力。

 

二:StringBuilder

   看這個類的話,還是看一下它的源代碼,就抽一個Append吧,從下面這個截圖中看出來幾個有意思的地方。

<1> 原來StringBuilder里面維護的是一個m_ChunkChars的字符數組。

<2> 如果當前的字符串的length<2,會直接給chunkchars數組復制,length>2的時候看到的是剛才string類中經典的wstrcpy用法,

      這個時候ptr指向的是chunkChars[chunkLength]的首地址,而不像string中申請新的內存空間,所以從這里看,比string大大的節省

    了內存空間。

 

好了,具體他們的性能比較我也不說了,大家看著他們的原理湊合著用吧,簡單的看看也只能看到這了,再看就漏點了。

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()