Использование Lazy<T> плохо для производительности?
Недавно у меня были некоторые проблемы с классом singelton, который лениво инициализировал словарь, где второй поток попытался бы использовать его до того, как он был фактически заполнен. Поэтому я реализовал инициализацию переменной через Lazy<T>
учебный класс.
Вот мой код:
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;
});
Это решило проблему, и теперь я рассматриваю возможность сделать это моей обычной практикой использования Lazy<T>
класс везде я делаю ленивую инициализацию, чтобы избежать возможных проблем с многопоточностью. В общем, я хотел бы знать, является ли это хорошей / обычной практикой? Или это будет вредно для производительности или что-то?
4 ответа
Трудно сказать, не зная, какой тип ограничений производительности у вас есть, но по моему опыту, одноразовая инициализация редко является узким местом (поскольку по определению это происходит только один раз). Lazy<T>
был написан, чтобы предоставить вам именно эту услугу, поэтому я бы порекомендовал использовать его.
Из документации я нахожу следующее:
Если в конструкторе Lazy не передается делегат, упакованный тип создается с помощью Activator.CreateInstance при первом доступе к свойству value. Если тип не имеет конструктора по умолчанию, генерируется исключение во время выполнения.
Activator.CreateInstance
это метод, который, как известно, плохо влияет на производительность. Однако в вашем случае это не кажется проблемой, и в любом случае, как сказал dlev, вызов метода один раз не будет проблемой. Я не видела Lazy<T>
используется очень часто, но я не вижу никаких причин не использовать его в вашем случае.
Если это для одиночного, статический конструктор может быть тем, что вы хотите. Что-то вроде:
class MySingleton
{
static MySingleton()
{
Instance().InitDict();
}
}
Я думаю, что вы можете использовать Lazy не по назначению. Ленивый должен использоваться в ситуациях, когда что-то имеет большие затраты на инициализацию, но есть вероятность того, что это не может быть использовано в течение срока службы объекта.
Если вы всегда звоните GroupDefaults
по крайней мере, один раз за время жизни лучшим методом будет инициализация GroupDefaults
в фоновом потоке в начале срока службы контейнера и надеюсь, что это будет сделано до его инициализации (я знаю, что для этого есть класс, но мне нужно покопаться в MSDN, чтобы найти его)