Найти тему

Открытия быстрого кода на C#

Продолжая тему того, что оптимизации применяются, причём в разных местах и весьма часто. Причём не хардкорные, а самые что ни на есть простейшие. И не по CPU, а по памяти.

Вот тут ребята из PVS-Studio узнали, что:

  1. Надо использовать правильный алгоритм. Это видно на примере их внутреннего кэша, где они складировали в память всё подряд. К кэшу в памяти надо всегда подходить с умом, так как кэш может распухнуть, а его данные вообще попасть в LOH.
  2. Одинаковые строки надо пропускать через string.Intern - это сильно экономит память. Опять таки, делать это надо осторожно.
  3. ToString создаёт... строку. Причём, иногда, по сложному алгоритму. Если таких вызовов много, то строки аллоцируются, память неумолимо заканчивается, GC не успевает. Не надо так, особенно в горячих местах кода.
  4. Итерация по IEnumerable несколько дорогая по памяти, если расположена в горячем месте. Это актуально для IList, IReadonlyList и прочих ICollection. Просто потому, что IEnumerator, который возвращается из IEnumerable.GetEnumerator(), хоть и структура по определению, но размещается в куче по использованию (boxing). Итерируйтесь по классам коллекций, это дешевле.
  5. LINQ это красиво, но очень дорого по памяти в горячих местах кода. Во-первых, произойдёт boxing IEnumerator как в пункте выше. Во-вторых, сами методы тоже иногда кое-что аллоцируют. Ну и скорость работы несколько ниже простого foreach. Разверните все LINQ в foreach в горячих местах кода.
  6. LINQ это штука, которая может выполняться несколько раз. Она ведь с отложенным выполнением. Значит каждый раз, когда мы будем передавать её в различные методы, каждый раз будет выполняться последовательность действий в цепочке выражений. Это дорого по CPU и по памяти. Не надо так. Лучше и дешевле материализовать результат один раз, сложить его в какой-нибудь массив, взятый из ArrayPool, и потом благополучно вернуть обратно.

Короче говоря, коллеги впечатлены: на некоторых проектах скорость работы увеличилась более чем на 20%, а пиковое потребление памяти сократилось практически на 70% (цитата из статьи). Что тут сказать? Только пожелать удачи и напомнить, что для некоторых типов задач не работает знаменитое правило о том, что преждевременная оптимизация это плохо. Увы, в некоторых проектах надо сразу писать код с оглядкой на память и CPU. Это окупится трижды, не потребует затрат на исследование возникших проблем и снизит негатив от пользователей.

P.S.: Понимаю, что статья старая, но очень уж показательная. Проблем с памятью не ожидаешь от инструмента, который, вроде бы, должен работать на пользовательских машинах.

Мой канал в TG: https://t.me/csharp_gepard