C# Heppard
1.56K subscribers
74 photos
2 files
122 links
25 способов эффективно использовать .NET

Поддержать канал можно тут: https://sponsr.ru/sharp_heppard
Download Telegram
Бенчмарк в контейнере #хранилища #бенч #анализ

Я тут произвёл замеры своего поделия для S3 с помощью DotMemory в контейнере с Debian. Понял, что про то, как это сделать не писал. Магические строчечки для вашего Docker-файла:


RUN apt-get update -y && apt-get install -y wget && \
wget -O dotMemoryclt.zip https://www.nuget.org/api/v2/package/JetBrains.dotMemory.Console.linux-x64/2022.3.3 && \
apt-get install -y unzip && \
unzip dotMemoryclt.zip -d ./dotMemoryclt && \
chmod +x -R ./dotMemoryclt/*

ENTRYPOINT ./dotMemoryclt/tools/dotmemory start-net-core --temp-dir=./src/dotMemoryclt/tmp --timeout=16m --save-to-dir=./src/dotMemoryclt/workspaces --log-file=./src/dotMemoryclt/tmp/log.txt --trigger-timer=2m ./src/publish/Storage.Benchmark.dll



Надо обратить внимание на ключи --timeout (чтобы отключить приложение после указанного времени работы) и --trigger-timer (время создания snapshot).

Всё делается с помощью консольной версии JetBrains DotMemory. После завершения работы берём файл по адресу --save-to-dir и открываем в DotMemory.
🔥10
Пуллинг массивов #память #статья

Предлагаю прочитать статью от некого Евгения про осторожное использование ArrayPool в многопоточной среде. Автор рассказал о том, как пул устроен и какие есть способы работать с ним для разных сценариев. Бенчмарки, схемы и разбор диагностик прилагаются.

Вот какие выводы были сделаны:

1. Пулинг объектов (в том числе массивов) помогает снизить аллокации и нагрузку на GC.

2. Неудачная или неподходящая для конкретного профиля нагрузки реализация пула может испортить производительность.

3. Для небольших массивов, нужных на короткое время, предпочтительно использовать масштабирующийся ArrayPool<T>.Shared.

4. Для больших массивов желательно использовать пул, созданный через ArrayPool<T>.Create как более вместительный и не разделённый по потокам.
👍85
Инициализация List #память #бенч

А вот мы решили создать List из уже существующего массива. Какой же способ выбрать, если нам важны наносекунды?

Ответ: любой.

Но если наносекунды нам действительно важны, то мы будем выбирать передачу массива в конструктор List'a. Внутри есть попытка каста IEnumerable к ICollection, что позволяет создать внутренний массив нужного размера. Именно его расширение является замедляющим фактором и причиной аллокации при вызове банального метода Add.

Инициализатор, конечно же, является синтаксическим сахаром многократного вызова метода Add (это отчётливо видно в IL).
👍12👏2
Ещё рекомендую посмотреть видосик о том, как стараются ускорить EF до уровня Dapper. Я, как многие знают, не очень уважаю EF. При этом я понимаю, что в обычной промышленной разработке без ORM тяжело, так как, пока мы строим планы, заказчик быстро и ощутимо меняет ландшафт.

Если кратко, мужчина предлагает функционал предкопилированных выражений для EF.
Подход интересный, который сильно похож на SQL в коде. Но это моё мнение.

Кстати, более подробно про улучшения производительности EF можно прочитать тут.

Программистам-волейболистам спасибо за видео!

#хранилище #лекция
👍3
Быстрый маппер #решение #бенч #скорость #память

А вот маппер. Несколько лет назад я писал статью о том, как вы можете сделать свой маппер на коленке. Сейчас мир изменился, и я хотел бы рассказать про Mapster. Штука годная, быстрая, гораздо лучше, чем AutoMapper. Обратите внимание, что разница между кодом маппинга, который я написал руками, и кодом правильного вызова Mapster'a - минимальная.

Важно. Для тех, кто пользуется Mapster'ом, я бы, при маппинге в коллекции, посоветовал бы брать функцию маппинга, а не использовать встроенную функцию маппинга (видимо там производится поиск необходимого маппера). Понимаю, что можно маппить список в список, но случаи бывают разные, а значит выражение TypeAdapter<TIn, TOut>.Map нужно запомнить.

Код я залил вот сюда, так как его многовато.

Кто-то знает, почему Mapster работает так быстро? Ответ очевиден, но вдруг кто-то не знает. Ответ явно будет в комментах.

P.S.: Я сторонник "ручного" маппинга, если что. Так понятнее, так будет более высокий контроль и так мы экономим наносекунды.
👍102
Отвыступал. Надеюсь, получилось интересно.
🔥274👍1
Оказывается, презентацию c DotNext выступления можно скачать тут. Видео будет через полгода.

#выступления
🔥74👏2
Кстати, хотел с вами поделиться хорошим обзором книги Конрада Кокосы Pro .NET Memory Management. Обзор для начинающих, то есть тех, кто вообще не особо в теме того, что написано в книге и кто такой Конрад. Степан, увы, не специализируется на производительности, но очень хорошо рассказывает.

https://www.youtube.com/watch?v=cXbZrLNSPvY

#память
👍9🤔2
После недавнего инцидента на проде, захотелось пересмотреть видео "Коленька, ты чо задеплоил". Не совсем про перформанс. Вернее, совсем не про перформанс.

https://www.youtube.com/watch?v=K6oZuB8_dU8

#отдых
👍42🔥1
Rust глазами дотнетчиков #лекция #rust

Набор подкастов по Rust от C# разработчиков. Парни хохмят, пытаются объять предысторию и делятся мнениями. Из минусов - очень долго, но мне такое нравится. Если интереснее более классическое изложение материала, то Кладов до сих пор очень крут.

Если приятнее читать, а не слушать, то можно сходить вот сюда.
👍9
Проблемы ситибилдера #игра #скорость #память

Я очень люблю градостроительные симуляторы. Выход Cities: Skylines 2 дал мне возможность слегка по иному взглянуть на этот тип игр. А именно, с точки зрения "преждевременная оптимизация это зло". Кажется, что мужики по полной использовали этот спорный тезис, так как игра выдаёт весьма скромные результаты при весьма не кислом потреблении ресурсов.

У меня достаточно хороший ноут, который тянет RDR2, Киберпанк и кривой порт tLOA. На весьма хороших настройках. А вот Cities: Skylines 2 тормозит.

Вот тут коллега пытается разобраться, а в чём, собственно, дело.

https://habr.com/ru/articles/772082/
https://habr.com/ru/articles/772284/

P.S.: И да, дело не в ECS (в Unity оно называется DOTS), а в банальном... я даже не знаю... пофигизме к производительности. Мужики делали игру про город, где графика как бы не так уж и важна, и смогли наступить почти на все графические грабли. Печально. Радует, что поправимо.
🔥7😁2👍1
Scoped в Singleton #отдых #архитектура

Я вот помню, на собесах спрашивали - можно ли Scoped звать из Singleton.
Так что, получается, можно или нет?

var provider = new ServiceCollection()
.AddScoped<Scoped>()
.AddSingleton<Singleton>()
.BuildServiceProvider();

provider.GetRequiredService<Singleton>();

public class Scoped
{
public string Say() => "Scoped in Singleton";
}

public class Singleton
{
public Singleton(Scoped scoped)
{
Console.WriteLine($"{scoped.Say()}, World!");
}
}
😁6👍3🤯2
Медленное интернирование #память #бенч

Есть вот такое мнение при интернировании строк. Если вам нужно быстро, то надо в ConcurrentDictionary, а не string.Intern(x). Код бенчмарка внутри.

Недавно это разбирал некий Сергей Тепляков, а какой-то Евгений Пешков писал.
👍7🤔4
Проверка существования значения #бенч #скорость

А вот ещё один интересный бенч. Есть такой паттерн - проверка существования значения в переменной с помощью расширения "TryGet". Мол, если у нас оно есть, то true, а иначе false.

Ну то есть удобно сделать так:

if (id.TryGet(out var existsId)) query = query.Where(dbo => dbo.Id == existsId)


Есть моментик. Можно написать наиболее общую штуку, которая делает instance.Equals(default), а можно конкретное написать instance == Guid.Empty. Второе сильно быстрее.
🤯32
Работа с Excel #решение #память

Нашёл тут очень интересную библиотеку для работы с xlsx.

Пока первые результаты очень впечатляющие. Однако, судя по коду, человек просто сделал хорошо. Кажется, можно сделать лучше, но про это я пока промолчу - нет данных.

В целом же, рекомендую для рассмотрения замены EPPlusFree и ClosedXML, если у вас есть проблемы с производительностью. Или, например, памятью. Я это к чему. В EPPlus у нас файлик в 20 мб внезапно распаковался в какое-то страшное количество мегабайтиков, и мы упали с OutOfMemoryException.
🔥9👍4
Коллеги, если кто-то ходит в ClickHouse c помощью библиотеки у которой больше всего звёзд в github, то я вас немного расстрою. Кажется, это всего-лишь обёртка над HTTP. Причём не самая быстрая. Напомню, что ClickHouse поддерживает тот же GRPC.

#решение #хранилище
Продолжая тему с HTTP, хочется напомнить, что Trino поддерживает HTTP. Ну если вдруг вы не знаете, как к нему легко подключиться.

#решение #хранилище
Поиск пути #игра #алгоритм #память

Есть такой алгоритм, называется A-Star (A*) - он нужен для поиска оптимального пути в 2D пространстве. Если вы не знали, то для него есть хорошая штука в базовых коллекциях .NET, называется PriorityQueue (завезли в .NET 6). Мотивация, в принципе, была очевидна - очень востребованная коллекция в играх (привет Unity).

Очередь с приоритетами - основной элемент алгоритма поиска пути. Когда я отчаиваюсь писать для энтерпайза и начинаю писать свою стратегическую игру, я снова и снова воспроизвожу A*. Про очередь с приоритетами недавно писал некий Степан, а до него писали вот тут.

Кстати, этот же алгоритм очень полезен на собеседованиях, где есть алгоритмическая секция. Например, знание устройства очереди с приоритетами помогало мне на собесах в Яндекс или Тинькофф.
🔥10👍5
Копирование массива #скорость #бенч

А вот Array.Copy. Мы можем соревноваться с ним в виде поэлементного копирования массива или, даже, сделать буффер на стеке через stackalloc и пытаться перемещать через него.

Увы, не поможет. Array.Copy будет быстрее за счёт, например, memmove. Там есть ещё пара ухищрений, но я рекомендую посмотреть их лично, перейдя к исходникам.

По вопросам реализации в своё время был интересный тред на github. Там такая масса подробностей, что мозг может задымиться.

Для нас это всё должно значить примерно следующее: по возможности нужно использовать Array.Copy (пусть даже это в виде stream.ReadAsync(buffer), а не писать велосипеды в виде побайтного копирования потока.
👍9🔥4