Is using Lazy<T> bad for performance?
Asked Answered
D

4

12

Recently I was having some issues with a singelton class that was lazy initializing a dictionary where a second thread would try to use it before it had actually been populated. So I implemented the variable initialization through the Lazy<T> class.

Here is my code:

private static Dictionary<string, string> GroupDefaults
{
    get { return mGroupDefaults.Value; }
}
private static Lazy<Dictionary<string, string>> mGroupDefaults =
    new Lazy<Dictionary<string,string>>(delegate
    {
        Dictionary<string, string> defaults = new Dictionary<string, string>();
        foreach (KeyValuePair<string, UnitGroup> groupDef in Groups)
            defaults.Add(groupDef.Key, groupDef.Value.First().Key);
        return defaults;
    });

This fixed the problem and now I am considering making this a regular practice of mine to use the Lazy<T> class anywhere I do lazy initialization to avoid any possible threading issues. So basically I would like to know if this is good/common practice? Or will it be detremental to performance or something?

Drusilla answered 28/6, 2012 at 1:10 Comment(0)
S
13

It's pretty hard to say without knowing what type of performance constraints you have, but in my experience, one-time initialization is rarely a bottleneck (since by definition it only occurs once.) Lazy<T> was written to provide you with this exact service, so I would recommend using it.

Stableman answered 28/6, 2012 at 1:15 Comment(4)
@AlexHopeO'Connor That's why it was added! The downside of using the class is that the declaration of the field/property becomes a little messier (as you can see) but performance-wise, it's solid.Stableman
Thats all I needed to hear, its just I have not seen many examples of it in other peoples code.Kerekes
@AlexHopeO'Connor It was only added to the framework in v4.0, so it hasn't been around all that long. Combine that with it being somewhat of a niche class, and you end up encountering it infrequently.Stableman
what about the optional isThreadSafe arg in the Lazy<T> constructor? I would think this should be false if you want the best performance and thread safety is not a factorShemeka
S
4

From the documentation, I find the following:

If no delegate is passed in the Lazy constructor, the wrapped type is created by using Activator.CreateInstance when the value property is first accessed. If the type does not have a default constructor, a run-time exception is thrown.

Activator.CreateInstance is a method that is notoriously bad for performance. However, that doesn't seem to be a problem in your case, and at any rate, as dlev said, invoking the method once wouldn't be a problem. I haven't seen Lazy<T> used very often, but I do not see any reason not to use it in your case.

Samalla answered 28/6, 2012 at 1:31 Comment(0)
H
2

If this is for a singleton, a static constructor might be what you want. Something like:

class MySingleton
{
    static MySingleton()
    {
         Instance().InitDict();
    }
}
Horsemanship answered 28/6, 2012 at 1:27 Comment(0)
Z
1

I think you may be using Lazy for not it's intended use. Lazy is to be used for situations where something has a large initialization cost, but there is a probable chance that it may not be used during the lifetime of the object.

If you always call GroupDefaults at least once per it's lifetime a better method would be to initialize GroupDefaults in a background thread at the start of the container's lifetime and hope that it is done before it is done initializing (I know there is a class for this but I need to dig in to the MSDN to find it)

Zennie answered 28/6, 2012 at 1:17 Comment(2)
While I agree that is the intended use case, it also implements thread-safe initialization correctly, so you don't have to worry about doing so yourself.Stableman
I was initializing it from another thread, however, the initialization would not complete before other stuff loading side by side tried to access it. Its a very odd situation where I can't afford to load sequentially as it would add a fair amount of time to load times. So I am spawning a number of threads that do a fair amount of work before they get held up due to GroupDefaults not being initialized, resulting in overall faster load times. However I am basically asking what would be a negative effect of using this class? What are its down sides?Kerekes

© 2022 - 2024 — McMap. All rights reserved.