爲什麼連接字符串一定要用StringBuilder(介紹CLR Profiler)

當然啦,很多人開始學習C#的時候,就已經聽到過來自多方的警告,連接字符串的時候一定要用StringBuilder,不要使用String直接連接的方式,而且也都知道其中的原因,例如什麼因爲String是一個固定的變量,不能更改,每一次String連接的操作實際上都是創建了一個新的String實例。可能很少有人知道具體的數據是什麼,因爲我們不能盡信書本上說的,一定要有一些實驗數據纔可以。

 

讓我們看下面的兩份代碼,一份是使用String來進行字符串連接操作的:

using System;

 

public class StringTest

{

    public static void Main()

    {

        string str = "";

 

 

        DateTime begin = DateTime.Now;

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

            str += i;

        DateTime end = DateTime.Now;

 

        Console.WriteLine(begin - end);

    }

}

 

另外一份是使用StringBuilder來進行字符串連接操作的。

using System;

using System.Text;

 

public class StringBuilderTest

{

    public static void Main()

    {

        StringBuilder str = new StringBuilder();

 

        DateTime begin = DateTime.Now;

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

            str.Append(i);

        DateTime end = DateTime.Now;

 

        Console.WriteLine(end - begin);

    }

}

 

當然啦,結果是大家都已經知道的,就是String版本的程序的速度要比StringBuilder的速度慢很多。

 

 

 

爲什麼String版本的程序會比StringBuilder程序慢那麼多呢已經不是簡簡單單的倍數級別的差別了。這裏我介紹一個工具—CLR Profiler,程序員可以使用這個工具瞭解到自己的程序到底創建了多少個對象,GC發生了多少次,以及各個函數之間的調用關係是怎樣的。

 

1.         下載CLR Profiler以後,啓動它,點擊“Start Application”按鈕。

2.         選擇我們要剖析的.NET程序,實際上CLR Profiler還可以剖析我們的ASP.NET網站程序。

3.         等待程序執行完畢,CLR Profiler就會詳細地給你列出整個程序運行過程當中發生的問題了。

 

例如下圖(這個圖比上面的示例程序的循環次數少,只有原來的十分之一,因爲示例程序生成的日誌文件太大,我機器的內存被消耗光了),我們可以看到系統分配了379,458,639也就是將近400M的內存,而最後Final Heap內存的大小隻有355,527—就是最後我們的連接起來的最終字符串的大小,而整個循環過程當中,有340 + 19次的GC操作,我們知道GC操作是非常耗費時間的一個操作,這也就是爲什麼我們看到String版本的程序運行速度如此之慢。

 

 

點擊上圖裏面的“Allocation Graph”之後,我們會發現所有的內存分配操作都是爲System.String執行的,在內存當中,String的實例有20231個,佔去被分配內存空間的99.96%

 

發佈了73 篇原創文章 · 獲贊 2 · 訪問量 39萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章