在 .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 的結果,代碼如下
使用 Benchmark 測試數據,需要在方法上加上 Benchmark attribute,使用 string 的相加測試的代碼如下
- 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]
- 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();
- }
使用 string.Format,測試的代碼如下
- [Benchmark]
- public void StringBuilderClear()
- {
- _sb.Clear();
- _sb.Append(firstWord);
- _sb.Append(secondWord);
- string s = _sb.ToString();
- }
使用 C# 6.0 提供的新語法 Interpolation,測試的代碼如下
- [Benchmark]
- public void Format()
- {
- string s = string.Empty;
- s = string.Format("{0} {1}", firstWord, secondWord);
- }
使用 string.Concat,測試的代碼如下
- [Benchmark]
- public void Interpolation()
- {
- string s = string.Empty;
- s = $"{firstWord}{secondWord}";
- }
使用 string.Join,測試的代碼如下
- [Benchmark]
- public void Concat()
- {
- string s = string.Empty;
- s = string.Concat(firstWord, secondWord);
- }
接著調整到 Release mode,按下 F5 進行測試
- [Benchmark]
- public void Join()
- {
- string s = firstWord;
- s += string.Join(s, secondWord);
- }
測試完成後,會產生測試報各路徑在 release\BenchmarkDotNet.Artifacts\results 目錄底下,如下圖所示
根據測試結果
感想
參考
在 ASP.NET Core 中使用多個環境
0 意見:
張貼留言