Анализатор обнаружил возможность оптимизации операций конкатенации внутри часто выполняемого метода.
Конкатенация приводит к созданию нового объекта строки, а значит и к дополнительному выделению памяти в управляемой куче. В целях повышения производительности этого следует избегать в часто выполняемом коде. В случае если к значению строки нужно несколько раз добавить различные фрагменты, вместо конкатенации разработчиками Unity рекомендуется использовать тип 'StringBuilder'.
Рассмотрим пример:
[SerializeField] Text _stateText; .... void Update() { .... string stateInfo = ....; .... stateInfo += ....; stateInfo += ....; .... stateInfo += ....; _stateText.text = stateInfo; .... }
Здесь реализовано построение строки 'stateInfo' путем нескольких операций конкатенации. Выполнение этого кода в методе 'Update' (вызывается несколько десятков раз в секунду), приведет к быстрому накоплению 'мусора' в памяти и к более частому вызову сборщика мусора для его очистки. Последнее может негативно отразиться на производительности. Избежать лишнего выделения памяти можно с помощью объекта 'StringBuilder':
[SerializeField] Text _stateText; .... StringBuilder _stateInfo = new StringBuilder(); void Update() { _stateInfo.Clear(); .... _stateInfo.AppendLine(....); _stateInfo.AppendLine(....); .... _stateInfo.AppendLine(....); _stateText.text = _stateInfo.ToString(); .... }
Метод 'Clear' очищает содержимое 'StringBuilder', но при этом не освобождает выделенную память. Таким образом, дополнительное выделение памяти потребуется только в том случае, если уже используемой будет недостаточно для хранения нового текста.
Рассмотрим другой пример:
[SerializeField] Text _text; .... List<string> _messages = new(); .... void LateUpdate() { .... string message = BuildMessage(); _text.text = message; _messages.Clear(); } string BuildMessage() { string result = ""; foreach (var msg in _messages) result += msg + "\n"; return result; }
В этом примере сообщение, выводимое на интерфейс, формируется с помощью метода 'BuildMessage'. Так как он вызывается внутри 'LateUpdate' (так же часто, как и внутри 'Update'), его тоже стоит оптимизировать:
StringBuilder _message = new StringBuilder(); string BuildMessage() { _message.Clear(); foreach (var msg in _messages) _message.AppendLine(msg); return _message.ToString(); }