2011-04-23 111 views
1

我們真的需要System.Lazy嗎?假設我的類庫有100個靜態類,每個靜態類使用平均100個靜態System.Lazys = 10000 System.Lazys,當使用我的類庫的程序啓動時,它必須啓動?c#vb:我們真的需要System.Lazy嗎?

我的意思是我們通常不僅使用1個類庫,比如說我們導入了15個.dll,他們每個人都有一噸靜態System.Lazys ..我很確定它需要很長時間才能啓動所有那些System.Lazys,更不用說它將囤積大量內存(因爲每個都有自己的System.Func讓我們把它放在每個內存中的50個字節= 500kb)

所以我想知道..是最好的只是用「舊」的方式(如使用布爾值來跟蹤是否啓動了某個東西)

+1

什麼讓你「相當肯定」有一個性能損失?你測過它了嗎? – jeroenh 2011-04-23 19:06:22

+2

沒有什麼比使用OOP語言進行100個靜態類的程序編程...就像在Haskell中做OOP一樣;這是一個壞主意。 – alternative 2011-04-23 19:08:37

+0

@jeroenh nop,但我想如果我應該在所有的靜態類使用Lazys – Pacerier 2011-04-23 19:09:01

回答

7

如果1)有很好的機會不需要該實例,那麼應該只使用Lazy 2)旋轉實例的成本足夠高證明開銷。

如果你在一個類中有100個靜態懶惰成員,你幾乎肯定會做錯。

+1

下面是一個很好的例子,爲什麼懶惰有道理 - 因爲正確地處理事情,而手動(沒有懶惰)比看起來更難: http://geekswithblogs.net/BlackRabbitCoder/archive/2010/05/19/c- system.lazylttgt-and-the-singleton-design-pattern.aspx – 2013-04-17 19:06:49

+1

我想我的答案沒有把它拼出來,但你絕對應該使用'Lazy'而不是自己實現線程安全的懶惰實例化。如果線程安全並不重要,並且分析器建議'懶惰'是有問題的(這看起來不太可能),那麼「老方法」可能會更好。但最重要的是:如果一個類的100個屬性需要是懶惰的,那麼這可能是一種代碼味道。 – dahlbyk 2013-04-18 23:22:45

2

Lazy<T>僅用於謹慎使用,在圖形中延遲加載對象是有意義的。也就是說,對於的對象可能不需要,但可能是,並且如果獲取這些對象的成本很高。

爲此,他們是一個很好的解決方案。

如果您知道您將使用所有對象,請勿使用Lazy<T>

+0

我說得對,懶惰有其開銷(關於我們在典型程序中使用的類的數量,這是不可忽略的) – Pacerier 2011-04-23 19:12:36

+0

懶惰增加了兩種開銷:內存中的額外實例(不多)和額外處理保持單身。如果您選擇線程安全的LazyThreadSafetyMode,額外的處理將會更高。總而言之,如果你的配置文件只是知道這些成本如何影響你的應用程序 - 與I/O等緩慢的東西相比,它們可能並不重要。 – dahlbyk 2011-04-23 19:19:29

3

正如其他人所說,如果您需要這種惰性初始化,您會遇到更大的問題。

但無論如何,只是爲了說明你應該如何自己處理這個問題:在做出假設之前進行測量。

下面的程序(受ayende啓發)度量了創建和初始化一個簡單分配新對象的Lazy()實例的開銷。

輸出我的機器上:

Created 583599 objects in 00:00:01.0000117 
Created 679939 objects in 00:00:01.0039926 
Created 688751 objects in 00:00:01.0000013 
Created 678244 objects in 00:00:01.0000018 
Created 682506 objects in 00:00:01.0000018 
Created and initialized 516400 lazy objects in 00:00:01.0000018 
Created and initialized 526585 lazy objects in 00:00:01.0000049 
Created and initialized 519425 lazy objects in 00:00:01.0000018 
Created and initialized 514477 lazy objects in 00:00:01.0000022 
Created and initialized 523544 lazy objects in 00:00:01.0005176 
Performance loss: 21,5091944284387 % 

不要從此得出一般性結論,因爲性能問題是很多時候非常具體到當時的情況。

但正如你所看到的,通過Lazy主場迎戰只需通過new分配它實例化對象的開銷比較小,因爲Lazy應該是通常情況下延遲實例化是有益的(即貴,和對象構造有一個很好的機會沒有實際需要)

class Program 
{ 
static void Main(string[] args) 
    { 
     var sequence = Enumerable.Range(1, 5); 

     var q1 = from s in sequence 
       select GenerateSimpleObjects(); 

     var q2 = from s in sequence 
       select GenerateAndInitializeLazies(); 

     var m1 = q1.Average(); 
     var m2 = q2.Average(); 

     Console.WriteLine("Performance loss: {0} %", 100 - 100 * m2/m1); 

    } 

    static void GenerateSimpleObjects() 
    { 
     var sp = Stopwatch.StartNew(); 

     int i = 0; 
     while (sp.ElapsedMilliseconds < 1000) 
     { 
      new object(); 
      i++; 
     } 
     sp.Stop(); 
     Console.WriteLine("Created {0} objects in {1}", i, sp.Elapsed); 
    } 


    static void GenerateAndInitializeLazies() 
    { 
     var sp = Stopwatch.StartNew(); 

     int i = 0; 
     while (sp.ElapsedMilliseconds < 1000) 
     { 
      var l = new Lazy<object>(() => new object()); 
      var o = l.Value; 
      i++; 
     } 
     sp.Stop(); 
     Console.WriteLine("Created and initialized {0} lazy objects in {1}", i, sp.Elapsed); 
    } 
} 
+0

實際上我所說的開銷不是「速度」,而是記憶。如果每個都需要50個字節,並且有10K已經是500kb的內存 – Pacerier 2011-04-23 21:55:08

+0

你的話:「我敢肯定它將花費很長時間來啓動所有這些System.Lazys,更不用說它將囤積大量的內存」。首先關注那句話,因爲我讀到它是關於表現......而關於記憶的使用:這也很容易通過簡單的計算或實驗來評估。 – jeroenh 2011-04-23 21:58:54

+0

確定我的錯誤.. – Pacerier 2011-04-23 22:10:12