c#vb:我们真的需要System.Lazy吗?

时间:2011-04-23 19:00:57

标签: .net static-classes

我们真的需要System.Lazy吗?假设我的类库有100个静态类,每个静态类使用平均100个静态System.Lazys = 10000 System.Lazys,当使用我的类库的程序启动时必须启动它?

我的意思是我们通常不只使用1个类库,比如我们导入15个.dll每个都有大量的静态System.Lazys ..我很确定它会花很长时间启动所有这些系统.Lazys,更不用说它也会囤积大量的内存(因为每个内存都有自己的System.Func让它每个50字节=内存500kb)

所以我想知道..最好是以“旧”的方式做到这一点(就像使用布尔来跟踪某些事情是否已经启动)

3 个答案:

答案 0 :(得分:7)

如果1)很可能不需要实例,那么你应该只使用Lazy; 2)启动实例的成本足以证明开销的合理性。

如果一个类中有100个静态惰性成员,那么你几乎肯定做错了。

答案 1 :(得分: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);
    }
}

答案 2 :(得分:2)

Lazy<T>意味着谨慎使用,在图中延迟加载对象是有意义的。也就是说,对于可能不需要的对象,但可能,并且获取它们的成本很高。

为此,他们是一个很好的解决方案。

如果知道您将使用所有对象,请不要使用Lazy<T>