2012-07-03 81 views
2

我剛剛進入函數式編程並試圖瞭解何時應該使類/屬性變爲可變。不可變性會導致性能問題嗎?

當字符串連接的顯著數量的工作,我們知道它是更好地使用StringBuilder,例如:

using System; 
using System.Diagnostics; 
using System.Text; 

namespace ConsoleApplication3 
{ 
    internal class Program 
    { 
     private static string myStr; 
     private static readonly StringBuilder mySb = new StringBuilder(); 

     private static void Main(string[] args) 
     { 
      Profile("+", 100000,() => myStr = myStr + "a"); // Takes 2236 ms 
      Profile("SB", 100000,() => mySb.Append("a")); // Takes 1 ms 
     } 

     private static void Profile(string description, int iterations, Action func) 
     { 
      // clean up 
      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 
      GC.Collect(); 

      // warm up 
      func(); 

      Stopwatch watch = Stopwatch.StartNew(); 
      for (int i = 0; i < iterations; i++) 
      { 
       func(); 
      } 
      watch.Stop(); 
      Console.Write(description); 
      Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds); 
     } 
    } 
} 

這就是俗稱情況,其中它的顯著更高性能的連接字符串通過StringBuilder而不是+運營商。我的假設是StringBuilder通過創建更少的字符串實現更好的性能。

性能和不變性之間是否存在平衡,還是由於某種原因,這種情況是例外情況?

回答

6

有效地連接字符串不是關於可變與不可變結構的關係,更關於選擇正確的數據結構和評估策略以支持追加。

通常,各種樹都用於支持快速附加,這可以最大限度地實現共享,並最大限度地減少複製。示例結構包括ropesfinger trees

在某些情況下,懶惰評估也有幫助(例如,如果連接涉及複製,那麼可以延遲到實際需要字符串尾部時)。在這種情況下,嚴格的數據結構可能會導致額外的複製開銷,從而進行超出必要的工作量。

在你的情況,我懷疑+涉及的參數的嚴格複製(即O(N + M))工作,而字符串生成器,可以通過分攤字符串緩衝區的再分配避免一些工作(以樹形結構的性能爲代價,其代價是線性使用結構,並且失去線程安全性)。

+0

我從這個答案中得到了兩件事 - 1.在某種程度上,這是一個例外(該算法更應歸咎於數據結構的可變性)和2.一般來說,你似乎支持智能算法,簡單數據結構陣營。這是一個公平的總結嗎? –

+0

@ MarkStafford-MSFT對我來說這聽起來很公平。 – dubiousjim

相關問題