343

I found this article about Lazy: Laziness in C# 4.0 – Lazy

What is the best practice to have best performance using Lazy objects? Can someone point me to a practical use in a real application? In other words, when should I use it?

Matthew
  • 25,652
  • 26
  • 93
  • 158
danyolgiax
  • 12,045
  • 10
  • 56
  • 100
  • 48
    Replaces: `get { if (foo == null) foo = new Foo(); return foo; }`. And there are zillions of possible places to use it... – Kirk Woll Jul 27 '11 at 16:15
  • 63
    Note that `get { if (foo == null) foo = new Foo(); return foo; }` is not thread-safe, while `Lazy` is thread-safe by default. – Matthew Jul 11 '13 at 23:00
  • 23
    From MSDN: IMPORTANT: Lazy initialization is thread-safe, but it doesn't protect the object after creation. You must lock the object before accessing it, unless the type is thread safe. – Pedro.The.Kid Mar 24 '14 at 14:50

7 Answers7

252

You typically use it when you want to instantiate something the first time its actually used. This delays the cost of creating it till if/when it's needed instead of always incurring the cost.

Usually this is preferable when the object may or may not be used and the cost of constructing it is non-trivial.

James Michael Hare
  • 35,710
  • 9
  • 67
  • 81
  • 130
    why not just ALWAYS use Lazy? – TruthOf42 Jun 11 '13 at 13:33
  • 48
    It incurs the cost at first use and may use some locking overhead (or sacrifices thread safety if not) to do so. Thus, it should be chosen carefully and not used unless needed. – James Michael Hare Jun 11 '13 at 20:23
  • 3
    James could you please expand on "and the cost of constructing is non-trivial"? In my case I have 19 properties in my class and in most cases only 2 or 3 will ever need to be looked at. Therefore I am considering implementing each property using `Lazy`. However, to create each property I am doing a linear interpolation (or a bilinear interpolation) which is fairly trivial but does have some cost. (Are you going to suggest that I go and do my own experiment?) – Ben Jan 31 '14 at 16:59
  • 3
    James, taking my own advice I did my own experiment. [See my post](http://stackoverflow.com/a/21491131/340045). – Ben Jan 31 '14 at 22:20
  • 17
    You may want to initialize/instantiate everything "during" system start-up to prevent user latency in high throughput, low latency systems. This is just one of the many reasons to not "always" use Lazy. – Derrick Sep 30 '14 at 12:34
  • 1
    @JamesMichaelHare `Lazy` is thread safe so you won't be sacrificing that. – Matt Kocaj Jul 06 '16 at 02:57
  • In WPF project I was instantiating a class to use it for data context of controls. but during construction of class I was opening a device with SafeHandle... and that's where the problems started. because designer tries to re-initialize my class every time and opening my device multiple times caused unexpected errors. This took me hours to find out whats going on. finally I figured it out and used `Lazy` to fix this issue. – M.kazem Akhgary Jan 01 '17 at 21:59
  • It seems common to use inside a Singleton. – eaglei22 May 02 '17 at 17:15
  • Awesome use case: ConcurrentDictionary.TryAddValue, when called from multiple threads with the same key, will call the valueFactory on both threads, but only one of the values will be added. This is textbook "may or may not be used", and is therefore a great place to use Lazy. https://stackoverflow.com/a/12611341/88409 – Triynko Aug 31 '17 at 23:24
134

You should try to avoid using Singletons, but if you ever do need to, Lazy<T> makes implementing lazy, thread-safe singletons easy:

public sealed class Singleton
{
    // Because Singleton's constructor is private, we must explicitly
    // give the Lazy<Singleton> a delegate for creating the Singleton.
    static readonly Lazy<Singleton> instanceHolder =
        new Lazy<Singleton>(() => new Singleton());

    Singleton()
    {
        // Explicit private constructor to prevent default public constructor.
        ...
    }

    public static Singleton Instance => instanceHolder.Value;
}
Matthew
  • 25,652
  • 26
  • 93
  • 158
  • 42
    I hate reading You should try to avoid using Singletons when I'm using them :D ... now I need to learn why I should try to avoid them :D – Bart Calixto Aug 29 '13 at 05:58
  • 29
    I'll stop using Singletons when Microsoft stops using them in their examples. – eaglei22 May 02 '17 at 17:16
  • 7
    I tend to disagree with the notion of needing to avoid Singletons. When following the dependency injection paradigm, it shouldn't matter either way. Ideally, all of your dependencies should only be created once. This reduces pressure on the GC in high load scenarios. Therefore, making them a Singleton from within the class itself is fine. Most (if not all) modern DI containers can handle it either way you choose. – Lee Grissom Jun 29 '17 at 20:17
  • 1
    You dont have to use a singleton pattern like that, instead use any di container configure your class for singleton. The container will take care of the overhead for you. – VivekDev Nov 08 '17 at 12:22
  • Everything has a purpose, there is situations where singletons are a good approach and situations where it is not :). – Hawkzey Mar 04 '20 at 14:39
95

A great real-world example of where lazy loading comes in handy is with ORM's (Object Relation Mappers) such as Entity Framework and NHibernate.

Say you have an entity Customer which has properties for Name, PhoneNumber, and Orders. Name and PhoneNumber are regular strings but Orders is a navigation property that returns a list of every order the customer ever made.

You often might want to go through all your customer's and get their name and phone number to call them. This is a very quick and simple task, but imagine if each time you created a customer it automatically went and did a complex join to return thousands of orders. The worst part is that you aren't even going to use the orders so it is a complete waste of resources!

This is the perfect place for lazy loading because if the Order property is lazy it will not go fetch all the customer's order unless you actually need them. You can enumerate the Customer objects getting only their Name and Phone Number while the Order property is patiently sleeping, ready for when you need it.

Despertar
  • 19,416
  • 7
  • 69
  • 74
  • 36
    Bad example, as such lazy loading is usually already built into the ORM. You shouldn't start to add Lazy values to your POCOs to get lazy loading, but use the ORM-specific way to do that. – Dynalon May 23 '13 at 05:42
  • 62
    @Dyna This example is referring to the built-in lazy loading of an ORM because I think this exemplifies the usefulness of lazy loading in a clear and simple way. – Despertar May 23 '13 at 06:49
  • SO if you are making use of Entity Framework should one enforce their own lazy? Or does EF do it for you? – Zapnologica Jan 14 '14 at 09:17
  • 7
    @Zapnologica EF does all this for you by default. In fact, if you want eager loading (the opposite of lazy loading), you must explicitly tell EF by using `Db.Customers.Include("Orders")`. This will cause the order join to be executed at that moment rather than when the `Customer.Orders` property is first used. Lazy Loading can also be disabled via the DbContext. – Despertar Jan 15 '14 at 00:18
  • 3
    Actually this is a good example, as one might want to add this functionality when using something like Dapper. – tbone Aug 26 '15 at 21:58
  • Caching is also good real-world example. When you are loading a cache store from a repository, use lazy. Then the cache store will be loaded only after a first request comes in. – VivekDev Nov 08 '17 at 12:24
  • Yes but it has absolutely nothing to do with `System.Lazy<>`. Lazy-loading implemented by ORMs is a completely different issue. Their main concern is performance, not thread safety or anything that is related to concurrency. – haim770 Apr 15 '18 at 09:27
  • @haim770 OP asked about Lazy loading in regards to performance. – Despertar Apr 20 '18 at 03:31
  • Discussion about System.Lazy and ORMs lazy loading are always in terms of performance. But there is a clear difference between them. The former is discussed in terms of initializing non-trivial objects, and the latter is discussed in terms of loading entities from a database (mostly discussed is the N + 1 problem with lazy loading in ORMs). – Никола Караклић Sep 13 '19 at 10:25
43

I have been considering using Lazy<T> properties to help improve the performance of my own code (and to learn a bit more about it). I came here looking for answers about when to use it but it seems that everywhere I go there are phrases like:

Use lazy initialization to defer the creation of a large or resource-intensive object, or the execution of a resource-intensive task, particularly when such creation or execution might not occur during the lifetime of the program.

from MSDN Lazy<T> Class

I am left a bit confused because I am not sure where to draw the line. For example, I consider linear interpolation as a fairly quick computation but if I don't need to do it then can lazy initialisation help me to avoid doing it and is it worth it?

In the end I decided to try my own test and I thought I would share the results here. Unfortunately I am not really an expert at doing these sort of tests and so I am happy to get comments that suggest improvements.

Description

For my case, I was particularly interested to see if Lazy Properties could help improve a part of my code that does a lot of interpolation (most of it being unused) and so I have created a test that compared 3 approaches.

I created a separate test class with 20 test properties (lets call them t-properties) for each approach.

  • GetInterp Class: Runs linear interpolation every time a t-property is got.
  • InitInterp Class: Initialises the t-properties by running the linear interpolation for each one in the constructor. The get just returns a double.
  • InitLazy Class: Sets up the t-properties as Lazy properties so that linear interpolation is run once when the property is first got. Subsequent gets should just return an already calculated double.

The test results are measured in ms and are the average of 50 instantiations or 20 property gets. Each test was then run 5 times.

Test 1 Results: Instantiation (average of 50 instantiations)

Class      1        2        3        4        5        Avg       %
------------------------------------------------------------------------
GetInterp  0.005668 0.005722 0.006704 0.006652 0.005572 0.0060636 6.72
InitInterp 0.08481  0.084908 0.099328 0.098626 0.083774 0.0902892 100.00
InitLazy   0.058436 0.05891  0.068046 0.068108 0.060648 0.0628296 69.59

Test 2 Results: First Get (average of 20 property gets)

Class      1        2        3        4        5        Avg       %
------------------------------------------------------------------------
GetInterp  0.263    0.268725 0.31373  0.263745 0.279675 0.277775 54.38
InitInterp 0.16316  0.161845 0.18675  0.163535 0.173625 0.169783 33.24
InitLazy   0.46932  0.55299  0.54726  0.47878  0.505635 0.510797 100.00

Test 3 Results: Second Get (average of 20 property gets)

Class      1        2        3        4        5        Avg       %
------------------------------------------------------------------------
GetInterp  0.08184  0.129325 0.112035 0.097575 0.098695 0.103894 85.30
InitInterp 0.102755 0.128865 0.111335 0.10137  0.106045 0.110074 90.37
InitLazy   0.19603  0.105715 0.107975 0.10034  0.098935 0.121799 100.00

Observations

GetInterp is fastest to instantiate as expected because its not doing anything. InitLazy is faster to instantiate than InitInterp suggesting that the overhead in setting up lazy properties is faster than my linear interpolation calculation. However, I am a bit confused here because InitInterp should be doing 20 linear interpolations (to set up it's t-properties) but it is only taking 0.09 ms to instantiate (test 1), compared to GetInterp which takes 0.28 ms to do just one linear interpolation the first time (test 2), and 0.1 ms to do it the second time (test 3).

It takes InitLazy almost 2 times longer than GetInterp to get a property the first time, while InitInterp is the fastest, because it populated its properties during instantiation. (At least that is what it should have done but why was it's instantiation result so much quicker than a single linear interpolation? When exactly is it doing these interpolations?)

Unfortunately it looks like there is some automatic code optimisation going on in my tests. It should take GetInterp the same time to get a property the first time as it does the second time, but it is showing as more than 2x faster. It looks like this optimisation is also affecting the other classes as well since they are all taking about the same amount of time for test 3. However, such optimisations may also take place in my own production code which may also be an important consideration.

Conclusions

While some results are as expected, there are also some very interesting unexpected results probably due to code optimisations. Even for classes that look like they are doing a lot of work in the constructor, the instantiation results show that they may still be very quick to create, compared to getting a double property. While experts in this field may be able to comment and investigate more thoroughly, my personal feeling is that I need to do this test again but on my production code in order to examine what sort of optimisations may be taking place there too. However, I am expecting that InitInterp may be the way to go.

Ben
  • 2,951
  • 3
  • 31
  • 44
  • 28
    maybe you should post your test code for reproducing your output, because without knowing your code it will be hard to suggest anything – WiiMaxx Nov 27 '14 at 11:04
  • 1
    I believe the main trade-off is between memory usage (lazy) and cpu usage (not-lazy). Because `lazy` has to do some extra book-keeping, `InitLazy` would use more memory than the other solutions. It also might have a minor performance hit on each access, while it checks whether it already has a value or not; clever tricks could remove that overhead, but it would require special support in IL. (Haskell does this by making every lazy value a function call; once the value is generated, it's replaced with a function which returns that value every time.) – jpaugh Aug 28 '17 at 16:03
18

Just to point onto the example posted by Mathew

public sealed class Singleton
{
    // Because Singleton's constructor is private, we must explicitly
    // give the Lazy<Singleton> a delegate for creating the Singleton.
    private static readonly Lazy<Singleton> instanceHolder =
        new Lazy<Singleton>(() => new Singleton());

    private Singleton()
    {
        ...
    }

    public static Singleton Instance
    {
        get { return instanceHolder.Value; }
    }
}

before the Lazy was born we would have done it this way:

private static object lockingObject = new object();
public static LazySample InstanceCreation()
{
    if(lazilyInitObject == null)
    {
         lock (lockingObject)
         {
              if(lazilyInitObject == null)
              {
                   lazilyInitObject = new LazySample ();
              }
         }
    }
    return lazilyInitObject ;
}
Nkosi
  • 191,971
  • 29
  • 311
  • 378
Thulani Chivandikwa
  • 2,680
  • 23
  • 25
  • 6
    I always use a IoC container for this. – Jowen Feb 02 '15 at 13:57
  • 1
    I agree strongly on considering an IoC container for this. If however you want a simple lazy initialized object singleton also consider that if you do not need this to be thread safe doing it manually with an If may be best considering the performance overhead of how Lazy handles itself. – Thulani Chivandikwa Jul 02 '15 at 06:28
13

From MSDN:

Use an instance of Lazy to defer the creation of a large or resource-intensive object or the execution of a resource-intensive task, particularly when such creation or execution might not occur during the lifetime of the program.

In addition to James Michael Hare's answer, Lazy provides thread-safe initialization of your value. Take a look at LazyThreadSafetyMode enumeration MSDN entry describing various types of thread safety modes for this class.

Vasea
  • 4,703
  • 2
  • 24
  • 30
-3

You should look this example to understand Lazy Loading architecture

private readonly Lazy<List<int>> list = new Lazy<List<int>>(() =>
{
    List<int> configList = new List<int>(Thread.CurrentThread.ManagedThreadId);
    return configList;
});
public void Execute()
{
    list.Value.Add(0);
    if (list.IsValueCreated)
    {
        list.Value.Add(1);
        list.Value.Add(2);

        foreach (var item in list.Value)
        {
            Console.WriteLine(item);
        }
    }
    else
    {
        Console.WriteLine("Value not created");
    }
}

--> output --> 0 1 2

but if this code dont write "list.Value.Add(0);"

output --> Value not created

HMD
  • 2,067
  • 6
  • 23
  • 33
Tufy Duck
  • 62
  • 5