Stringbuilder組字串的效能一定比String好?那可不一定.
長久以來,一直有個模糊且不正確的觀念,雖然知道StringBuilder效能比String好,但並不清楚是在什麼樣的情況下比較好,加上最近有同事提到這部份的效能問題,於是就寫了一些程式來測看看,而這次反組譯程式也拿出來用了,主要是看原本程式的寫法在經過Compiler後會變為什麼樣子.
首先所要提到的幾個方式,是字串在設計階段就已經固定,在執行階段也不會有任何改變的做法,這種情況之下,String跟StringBuilder的效能表現,是否StringBuilder還是比String的做法還來的好.
{
string a = "abcdefghijklmnopqrstuvwxyz : " +
"abcdefghijklmnopqrstuvwxyz : " +
"abcdefghijklmnopqrstuvwxyz";
return a;
}
{
Return "abcdefghijklmnopqrstuvwxyz : abcdefghijklmnopqrstuvwxyz : abcdefghijklmnopqrstuvwxy";
}
{
string a = "abcdefghijklmnopqrstuvwxyz : ";
a += "abcdefghijklmnopqrstuvwxyz : ";
a += "abcdefghijklmnopqrstuvwxyz";
return a;
}
{
string a="abcdefghijklmnopqrstuvwxyz : ";
return (a+" abcdefghijklmnopqrstuvwxyz : "+" abcdefghijklmnopqrstuvwxyz");
}
{
StringBuilder s = new StringBuilder();
s.Append("abcdefghijklmnopqrstuvwxyz : ");
s.Append("abcdefghijklmnopqrstuvwxyz : ");
s.Append("abcdefghijklmnopqrstuvwxyz");
return s.ToString();
}
public string GetDynStr()
{
string a = "abcdefghijklmnopqrstuvwxyz : ";
if (z == x)
{
a += "abcdefghijklmnopqrstuvwxyz";
}
return a;
}
{
StringBuilder s = new StringBuilder();
s.Append("abcdefghijklmnopqrstuvwxyz : ");
if (z == x)
{
s.Append("abcdefghijklmnopqrstuvwxyz : ");
}
return s.ToString();
}
補充 :
或許用迴圈的方式,容易讓人有種錯覺,感覺自己的程式怎麼可能跑迴圈那麼多次,那就用String就好了,其實應該是要看變數裡的”資料量”,只是範例裡用的資料量都不多,所以才用大量迴圈的方式去凸顯出它的效能差異.如果今天資料量很大,不需要用迴圈,一次就可以看出它的差異,就以上面兩個程式做一些修改調整.
String 動態大量字串做法 1 (1次) :
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
string a = new string('a', 1000000);
sw.Start();
DynStrOnce(a);
sw.Stop();
MessageBox.Show(string.Format("耗時(毫秒) : {0} ", sw.ElapsedMilliseconds.ToString("#,##0")));
}
public string DynStrOnce(string a)
{
if (z == x)
{
a += "abcdefghijklmnopqrstuvwxyz";
}
if (z == x)
{
a += "abcdefghijklmnopqrstuvwxyz";
}
if (z == x)
{
a += "abcdefghijklmnopqrstuvwxyz";
}
return a;
}
String 動態大量字串做法 2 (1次) :
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
string a = new string('a', 1000000);
sw.Start();
DynStrBuOnce(a);
sw.Stop();
MessageBox.Show(string.Format("耗時(毫秒) : {0} ", sw.ElapsedMilliseconds.ToString("#,##0")));
}
public string DynStrBuOnce(string a)
{
StringBuilder s = new StringBuilder(a);
if (z == x)
{
s.Append("abcdefghijklmnopqrstuvwxyz");
}
if (z == x)
{
s.Append("abcdefghijklmnopqrstuvwxyz");
}
if (z == x)
{
s.Append("abcdefghijklmnopqrstuvwxyz");
}
return s.ToString();
}
for (int i = 0; i < 10000; i++)
{
tmps = string.Format("{0}{1}{2}",tmps, "T", i);
}
for (int i = 0; i < 10000; i++)
{
tmps += string.Format("{0}{1}", "T", i);
}
for (int i = 0; i < 10000; i++)
{
sb.AppendFormat("{0}{1}","T", i);
}
for (int i = 0; i < 10000; i++)
{
tmps = tmps+ "T"+i;
}
for (int i = 0; i < 10000; i++)
{
sb.Append("T");
sb.Append(i);
}
String 或 StringBuilder 物件之串連作業的效能是根據記憶體的配置頻率而定。String 串連作業永遠都會配置記憶體,而 StringBuilder 串連作業只有在 StringBuilder 物件緩衝區太小而無法容納新資料時,才會配置記憶體。因此,如果要串連固定數目的 String 物件,最好使用 String 類別的串連作業。在這種情況下,編譯器 (Compiler) 甚至可能將個別的串連作業結合成一個單一作業。如果要串連任意數目的字串 (例如,如果迴圈串連任意數目的使用者輸入字串),則對於串連作業來說最好使用 StringBuilder 物件。