Найти тему

Быстрый C#

Не только PVS-Studio (спасибо им за ключ) имеет проблемы с аллокацией памяти. Вот тут JetBrains рассказывают следующее:

  1. Надо выбрать хороший алгоритм. В них я разбираюсь плохо, поэтому советов давать не буду: какой-то вариант обхода графа объектов. Важно то, что подбор правильного алгоритма позволил снизить аллокацию с 1.17ГБ до 7.5МБ в секунду. Да, он стал медленнее, но оптимизация это вечная борьба между памятью и CPU.
  2. Не нужно создавать миллион Dictionary, даже если вам это очень удобно. Это достаточно сложный класс, который внутри себя содержит два массива, которые он ещё и периодически расширяет. Да, он очень удобен, но в горячем месте кода такое удобство может очень больно выстрелить.
  3. Переиспользование коллекций иногда может быть плохой идеей. Например, если Dictionary ранее содержал 20 тысяч элементов, то переиспользовать его не нужно. Это, например, сильно медленнее при очистке (с чем и столкнулись JetBrains). Тут есть два выхода. Либо писать свою коллекцию, которая не очищается, а просто переставляет указатель на первый элемент внутреннего массива. Либо сразу отбрасывать переиспользованную коллекцию, элементов в которой стало больше какого-то предела.
  4. Предпочитайте struct, если объем данных очень большой. Дело в том, что структура не имеет заголовочных данных класса, а значит занимает меньше памяти. В случае JetBrains, объем полезных данных в их классе всего 45 байт. Однако, с учетом заголовка объекта и выравнивания, экземпляр класса занимает 72 байта. Казалось бы копейки, но на большом объеме это будет бить очень больно.
  5. При переходе на структуры, нужно стараться уменьшить количество полей в структуре, чтобы она занимала меньше памяти. Однако, если мы боремся за CPU, то предвычисленные значения предпочтительнее.
  6. Обход по массиву структур несколько быстрее обхода массива классов, поскольку данные лежат сильно компактнее и их удобнее читать. На этом эффекте основана производительность некоторых ECS фреймворков для игр.

Коллеги не сделали относительных выводов по данной оптимизации и я их понимаю: приложение вообще отказывалось работать. Тем не менее, я взял максимумы из начала статьи и вынул калькулятор. Итак, увеличение скорости составило больше 90% (с 55 минут до 2 минут), а потребление памяти снизилось на 40% (с 20ГБ до 12ГБ).

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