Я заметил, что следующий код генерирует выделения кучи, которые в какой-то момент запускают сборщик мусора, и я хотел бы знать, почему это так и как этого избежать:
private Dictionary<Type, Action> actionTable = new Dictionary<Type, Action>();
private void Update(int num)
{
Action action;
// if (!actionTable.TryGetValue(typeof(int), out action))
if (false)
{
action = () => Debug.Log(num);
actionTable.Add(typeof(int), action);
}
action?.Invoke();
}
Я понимаючто при использовании лямбды, такой как () => Debug.Log(num)
, будет создан небольшой вспомогательный класс (например, <> c__DisplayClass7_0 ) для хранения локальной переменной.Вот почему я хотел проверить, могу ли я кэшировать это распределение в словаре.Однако я заметил, что вызов Update приводит к выделению ресурсов, даже если лямбда-код никогда не достигается из-за оператора if.Когда я комментирую лямбду, распределение исчезает из профилировщика.Я использую инструмент Unity Profiler (инструмент отчетности о производительности в игровом движке Unity), который показывает такие распределения в байтах на кадр в режиме разработки / отладки.
Я предполагаю, что компилятор или JIT-компилятор генерирует помощниккласс для лямбды для объема метода, хотя я не понимаю, почему это было бы желательно.
Наконец, есть ли способ кэшировать делегатов таким образом, не выделяя и не заставляя вызывающий код заранее кэшировать действие?(Я знаю, что я мог бы также выделить действие один раз в клиентском коде, но в этом примере я бы строго хотел реализовать какое-то автоматическое кэширование, потому что у меня нет полного контроля над клиентом).
Отказ от ответственности: это в основном теоретический вопрос из интереса.Я понимаю, что большинство приложений не получат такой микрооптимизации.