Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
V4003. Unity Engine. Avoid capturing va…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V4003. Unity Engine. Avoid capturing variable in performance-sensitive context. This can lead to decreased performance.

02 Авг 2023

Анализатор обнаружил захват переменной в лямбда-выражении внутри часто выполняемого метода. Захват переменных может приводить к снижению производительности из-за дополнительного выделения памяти.

Рассмотрим пример:

void Update()
{
  ....
  List<int> numbers = GetNumbers();
  int divisor = GetDivisor();
  var result = numbers.Select(x => x / divisor);
  ....
}

Здесь 'Update' — метод Unity, выполняющий покадровое обновление. Метод 'Update' — часто вызываемый, и его не рекомендуется нагружать лишними операциями.

В приведенном примере используется лямбда-выражение с захватом переменной 'divisor'. Как упоминалось ранее, захват переменной из внешнего контекста приводит к дополнительному созданию объекта.

Таким образом, представленный участок кода создает дополнительную нагрузку на GC.

Оптимальная реализация метода может выглядеть следующим образом:

void Update()
{
  ....
  List<int> numbers = GetNumbers();
  int divisor = GetDivisor();

  var result = new List<int>(numbers.Count);
  for (int i = 0; i < numbers.Count; i++)
  {
    result.Add(numbers[i]/divisor);
  }
  ....
}

Использование собственной реализации, аналогичной 'Select', позволяет избавиться от дополнительного выделения памяти и тем самым снизить нагрузку на GC.

Рассмотрим еще один пример:

void Update()
{
  ....
  List<int> numbers = GetNumbers();
  int divisor = GetDivisor();

  if (AreAllMultipleOf(numbers, divisor))
    ....
}

bool AreAllMultipleOf(List<int> lst, int divisor)
{
  return lst.All(elem => elem % divisor == 0);
}

Здесь из метода 'Update' вызывается метод 'AreAllMultipleOf', который определяет, являются ли все полученные числа кратными значению 'divisor'. Так же, как и ранее: 'Update' — часто вызываемый метод, выполняющий покадровое обновление в Unity.

В представленном случае метод 'AreAllMultipleOf' регулярно выполняется внутри 'Update', а значит, также является часто вызываемым.

Метод 'AreAllMultipleOf' для выполнения проверки использует лямбда-выражение с захватом переменных. Это приводит к дополнительному выделению памяти, которое может негативно сказаться на производительности приложения.

Оптимальная реализация может выглядеть следующим образом:

void Update()
{
  ....
  List<int> numbers = GetNumbers();
  int divisor = GetDivisor();

  if (AreAllMultipleOf(numbers, divisor)) 
    ....
}

bool AreAllMultipleOf(List<int> lst, int divisor)
{
  foreach (int num in lst)
  {
    if (num % divisor != 0)
      return false;
  }
  return true;
}

Здесь мы в очередной раз воспользовались собственной реализацией, что позволило избежать дополнительного выделения памяти и снизить нагрузку на сборщик мусора.

close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам