在 .NET 應用程式中很常使用到 string 型別,string 是不可變 ( Immutable ) 的,當每次建立完就會固定其長度,如果要做相加就必須捨棄原有使用的記憶體,在重新配置一塊新的記憶體給它使用,如果在需要大量得字串動態相加時就會影響到其效能,因此在動態文字相加情境就可以透過 stringBuilder 來改善此問題,詳細細節可以參考黑暗大的 StringBuilder串接字串的迷思,這篇重點是在 C# 有提供多種語法來做 string 相加語法,像是 string.Format、stringBuilder、Concat、Join 以及 Interpolation 多種方法,今天就要針對 C# 中提供的字串相加效能進行比較,以及測試的結果數據,若有問題或是錯誤的地方歡迎各位給予指導及討論。
測試代碼
測試方式以 BenchmarkDotNet 套件協助進行測試,BenchmarkDotNet 可以針對要測試的方法紀錄執行時間,並會將測試結果輸出報告,如果對此套件有興趣可以參考介紹的文章 [.NETCore] 使用 BenchmarkDotNet 測試程式碼效能,首先先針對固定字串相加做測試,定義區域變數 firstWord 與 secondWord 希望輸出 This is a book 字眼,另外在 stringBenchmark 類別加上 ClrJob,CoreJob 希望分別在 .NET Framework 與 .NET Core 測試效能差異,加上 MemoryDiagnoser 輸出測試時觀察 GC 的結果,代碼如下
namespace benchmarkLab { class Program { static void Main(string[] args) { var summary = BenchmarkRunner.Run<stringBenchmark>(); Console.ReadKey(); } } [MemoryDiagnoser] [ClrJob,CoreJob] public class stringBenchmark { private static string firstWord = "This is a"; private static string secondWord = "book"; StringBuilder _sb = new StringBuilder(); // 測試代碼 } }使用 Benchmark 測試數據,需要在方法上加上 Benchmark attribute,使用 string 的相加測試的代碼如下
[Benchmark] public void Normal() { string s = string.Empty; s = firstWord; s += secondWord; }
使用 stringBuilder 的相加測試的代碼如下
另外一種使用 stringBuilder 的方式,將其宣告為區域變數使用前先 clear,測試的代碼如下
測試完成後,會產生測試報各路徑在 release\BenchmarkDotNet.Artifacts\results 目錄底下,如下圖所示
根據測試結果
.NET Framework : 表現最差的為 string.Format,表現最好的是 string 相加
.NET Core : 表現最差的為 string.Format,表現最好的是 Interpolation
[Benchmark] public void StringBuilder() { StringBuilder sb = new StringBuilder(); sb.Append(firstWord); sb.Append(secondWord); string s = sb.ToString(); }
[Benchmark] public void StringBuilderClear() { _sb.Clear(); _sb.Append(firstWord); _sb.Append(secondWord); string s = _sb.ToString(); }使用 string.Format,測試的代碼如下
[Benchmark] public void Format() { string s = string.Empty; s = string.Format("{0} {1}", firstWord, secondWord); }使用 C# 6.0 提供的新語法 Interpolation,測試的代碼如下
[Benchmark] public void Interpolation() { string s = string.Empty; s = $"{firstWord}{secondWord}"; }使用 string.Concat,測試的代碼如下
[Benchmark] public void Concat() { string s = string.Empty; s = string.Concat(firstWord, secondWord); }使用 string.Join,測試的代碼如下
[Benchmark] public void Join() { string s = firstWord; s += string.Join(s, secondWord); }接著調整到 Release mode,按下 F5 進行測試
測試完成後,會產生測試報各路徑在 release\BenchmarkDotNet.Artifacts\results 目錄底下,如下圖所示
根據測試結果
感想
參考
在 ASP.NET Core 中使用多個環境
0 意見:
張貼留言