c# vb: do we really need System.Lazy?
Do we really need System.Lazy
? Let's say my class library have 100 static classes and each static class uses an average of 100 static System.Lazys = 10000 Syste开发者_开发百科m.Lazys that have to be initiated when a program that uses my class library starts?
I mean we usually don't only use 1 class library, say we import 15 .dlls each of them have a ton of static System.Lazys.. I'm pretty sure its gonna take a long time initiating all those System.Lazys, not to mention its gonna hoard a ton of memory as well (since each have its own System.Func let's put it at 50 bytes each =500kb in memory)
So I was wondering.. is it best to just do it the "old" way (like using a boolean to keep track of whether something is initated)
You should only use Lazy
if 1) there's a good chance the instance won't be needed, and 2) the cost of spinning up the instance is high enough to justify the overhead.
If you have 100 static lazy members in a class, you're almost certainly doing it wrong.
As the others have said, you have much bigger problems if you need this kind of lazy initialization.
But anyway, just to show how you should be handling this question yourself: MEASURE before making assumptions.
The program below (inspired by ayende) measures the overhead of creating and initializing a Lazy() instance that simply allocates a new object.
output on my machine:
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 %
Don't draw general conclusions from this because performance problems are many times very specific to the situation at hand.
But as you can see, the overhead of instantiating an object via Lazy
vs. simply allocating it through new
is relatively small, given that Lazy
should be typically in situations where delayed instantiation is useful (i.e. expensive, and the object constructed has a good chance of not being actually needed)
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);
}
}
Lazy<T>
is meant to be used sparingly, where it makes sense to lazy load objects in a graph. That is, for objects that are likely not needed, but may be, and if the cost for fetching them is high.
For that, they are a great solution.
If you know you will be using all of the objects, don't use Lazy<T>
.
精彩评论