C# 10 字串插補的效能改進

 我錄製了一個影片,展示 C# 10 的字串插補在效能方面改進了多少。


C# 10 (.NET 6) 的字串插補,無論執行速度還是記憶體的使用效率,都比 C# 9 (.NET 5) 好很多。那麼,效能究竟提升多少呢?我用一個簡單的小程式來測試,結果發現 C# 10 的字串插補比 C# 9 快了大約一倍,而且使用的記憶體也更省。


以下影片展示了測試過程與結果:



影片當中用來測試效能的小程式,已經放在我的 GitHub:StringInterpolationPerformanceTest

至於用來測試效能的 BenchmarkDotNet 套件,其用法可參考 marcus 學習筆記的文章:〈使用 BenchmarkDotNet 測試程式碼效能〉。

補充說明

影片中用來觀察執行效能的 Today 方法,只是單純用字串插補來組成「今天是某年某月某日」的字串:



在 C# 9,上列程式碼會被編譯成這樣:



也就是說,C# 9 使用了 string.Format() 來實現字串插補。此作法往往需要付出較高的成本,比如說,它必須額外配置一個陣列來存放引數、可能需要額外處理實質型別的裝箱(boxing)、無法減少非必要的字串建構……等等。

備註:什麼時候會碰到「非必要的字串建構」?一個常見的例子是輸出 Log 訊息的場合。比如說,log level 設定在 Error 等級才要輸出 log 訊息,但實際執行時,無論輸出的 log 訊息是什麼等級,該訊息的字串一定會事先建構起來。這種情況,到了 C# 10 便有了改善的機會。具體細節,待日後介紹「字串處理器」的時候會比較清楚些,或者您也可以閱讀 C# 官方文件來學習相關知識:Improved Interpolated Strings

到了 C# 10,則採取不同的作法,其轉譯結果會像這樣:



程式碼變多了,但執行速度卻更快,消耗的記憶體也更少。就如本文開頭影片中的測試結果,整體效能比 C# 9 的字串插補提升了一倍左右。在頻繁使用字串插補的場合(例如迴圈),效能差距會更加明顯。這樣的寫法有點 StringBuilder 的味道,對吧?只是這次完全由編譯器自動生成,不用我們自己手工一行一行去刻。


從上列程式片段的第 5 行可以發現,C# 10 的字串插補是用一個叫做 DefaultInterpolatedStringHandler 的結構來建構字串,這是 C# 10 預設的字串處理器。我們甚至可以自行設計特定用途的字串處理器,來減少一些不必要的字串連接操作,進一步提升程式的執行效能。關於自訂的字串處理器,之後有空再寫一篇文章來介紹吧。


Happy coding!

參考資料

沒有留言:

技術提供:Blogger.
回頂端⬆️