2011-04-23 113 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