我们真的需要System.Lazy
吗?假设我的类库有100个静态类,每个静态类使用平均100个静态System.Lazys = 10000 System.Lazys,当使用我的类库的程序启动时必须启动它?
我的意思是我们通常不只使用1个类库,比如我们导入15个.dll每个都有大量的静态System.Lazys ..我很确定它会花很长时间启动所有这些系统.Lazys,更不用说它也会囤积大量的内存(因为每个内存都有自己的System.Func让它每个50字节=内存500kb)
所以我想知道..最好是以“旧”的方式做到这一点(就像使用布尔来跟踪某些事情是否已经启动)
答案 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>
。