gram news
Аватар канала C# Heppard

C# Heppard

@csharp_gepard

25 способов эффективно использовать .NET Поддержать канал можно тут: https://sponsr.ru/sharp_heppard

1,650подписчиков

Открыть канал

Последние посты

  • C# Heppard

    13 мар., 10:27

    переслано из @ozon_tech

    Ozon Tech Community .NET Meetup24 марта, лофт Casa Picassa, 19:00 Ищем способы бороться с primitive obsession, отличать OrderID от ItemID, переживать нагрузку без каскадных отказов с load shedding и спасаться от аллокаций с помощью JIT-оптимизатора ❕➡И находим: вас ждут три доклада — немного про runtime-внутрянку, немного про хайлоад-сервисы, много-много кейсов из нашей .NET-практики.Когда трансляция подойдёт к концу, мы с вами, офлайн-гостями, останемся на импровизированной кухне — обсуждать спорные и неудачные решения без камеры, логов и трассировки. До утра вряд ли, но до глубины души наверняка.Есть ощущение, что места закончатся через 3…2…1… Так что не тяните с регистрацией ⬅️#ozontech_events #csharp
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
    1,75086431Открыть в Telegram
  • C# Heppard

    20 янв., 15:27изменён

    Ещё одна история про память #отдыхСудя по комментариям специалистов и ценам на RAM в магазинах, историю про память я буду рассказывать снова и снова. Это, конечно, не смищно.Но есть новая история.Недавно сосед предложил прийти к нему и посмотреть, а что ж у него с новым компом. Он прям вот вчера его купил. Не включается, не пищит, вообще не подаёт признаков жизни.Ну да, я же программист, я понимаю в компах. Для важности взял чемоданчик с инструментами. Ну где у меня лежат разные отвёртки, плоскогубцы и молоток.Пришёл, потыкал кнопку "вкл" и даже "ресет". Не помогло. Открыли корпус, осматриваю красивые внутренности. Корпус красивый, богатый, с "любимой" подсветкой. Видюха внушительная, процессор мощный такой, солидный. Провода разноцветные. И две плашки памяти, аж 64 Гб.Они мне сразу показались подозрительными. Я не часто видел плашки памяти, но явно не гуд, когда они как бы
    TelegramC# HeppardДокупить память или написать эффективно? #отдых 05.03.2024 в рамках процесса *оптимизации* использования ресурсов кластера kubernetes (***) будут выключены сервисы, развернутые в следующих неймспейсах... Когда я получаю подобные сообщения от корпоративной…
    2,4201061Открыть в Telegram
  • C# Heppard

    25 нояб. 2025 г., 06:31изменён

    FastEnum #скоростьИногда нам нужно не просто быстро, а очень быстро. В этот момент в дело вступают самые необычные оптимизации. Например, оптимизация работы с enum. Типичный сценарий - получить строку из enum'a или, наоборот, enum из строки.Многие знают, что получение строкового представления enum'a лучше делать через Enum.GetName(MyEnum.Value), а вариант MyEnum.Value.ToString() аллоцирует новую строку и несколько медленнее.В случае сложной логики получения строкового представления enum'a, чаще всего используется кэш (который, кстати, есть в Enum.GetName). Для этой цели можно написать свой класс, который содержит два словаря. В случае получения строки из enum'a мы идём по одному словарю, а в случае получения enum'a из строки - по другому. Код примерно такой: private static readonly FrozenDictionary<string, T> StringToValues; private static readonly FrozenDictionary<T, string>
    2,910201021Открыть в Telegram
  • C# Heppard

    20 нояб. 2025 г., 06:58изменён

    UnsafeAccessor #скоростьИногда возникает странное желание изменять приватные поля в классах, код которых нам не доступен. Например, внутренний массив коллекции или настройку, которая почему-то и, по нашей логике, возмутительно не выставлена наружу.В этом, не самом здоровом желании, нам, конечно, поможет reflection. Код будет тривиальный, что-то вроде typeof(Entry).GetField(...) . Этот код найдёт поле в типе и вернёт нам его объектное представление.Особо упорные ребята могут делать подобную операцию каждый вызов метода, но это крайне не оптимально на горячих участках кода. Более умные коллеги выполнят поиск поля один раз, положат его в статическую переменную и будут получать значение через fieldInfo.GetValue(_entry), а задавать через fieldInfo.SetValue(_entry, value).Те, кто читал про ExpressionTree, вполне резонно будут получать и задавать значение через заранее сформированные
    2,40030105Открыть в Telegram
  • C# Heppard

    17 нояб. 2025 г., 13:23изменён

    Latency numbers every programmer should knowЯ всё время теряю эти циферки, особенно когда они нужны в процессе ожесточённой беседы про производительность. Забываю ключевые слова для поиска, нахожу не те картинки.А ведь эти циферки очень полезны для всех, кто так или иначе интересуется производительностью. Эти цифры и картинка иллюстрируют, что, например, поход в БД значительно более приоритетная цель для оптимизаций, чем, например, замена List на Dictionary. Или что сеть может съесть все перформансные улучшения, связанные с переходом на struct и Span.Не забывайте про эти цифры, когда исследуете проблемы с производительностью. Смотрите на то, что реально тратит время (или память).Взял отсюда, а ссылаются ещё вот сюда.P.S.: Сами цифры вызывают вопросы, но в том, что их отношение друг к другу примерно такое - сомнений нет. P.P.S: Коллега ещё напоминает о стоимости операций. L1 cac
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
  • C# Heppard

    29 окт. 2025 г., 08:33изменён

    Dictionary.TryGetValue #скоростьУж сколько лет прошло и, вроде, все это знают. Но, тем не менее, периодически на собеседование приходит человек, который пишет не оптимальный код извлечения значения из словаря. Я увидел, что я про это не писал, поэтому напомню ещё раз это элементарное правило.Коллеги, если у нас есть сценарий: проверить существование ключа в Dictionary и извлечь соответствующее ему значение, то не надо делать ContainsKey, а потом извлекать значение. В словаре есть прекрасный метод TryGetValue, который проверяет наличие ключа и, если он есть, тут же, не отходя от кассы, извлекает значение. Это быстрее примерно на 20-30%.А почему использование TryGetValue быстрее? Ведь поиск в Dictionary это O(1), типа очень быстро. Но надо вспомнить, что O(1) это алгоритмическая сложность, не абсолютные цифры. Это про то и только про то, что скорость поиска не зависит от количества
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
  • C# Heppard

    27 окт. 2025 г., 13:45изменён

    Надо тренироваться #отдыхПриехали фото с конференции. Я что-то толстоват. Поэтому понял, что надо усилить тренировки. Я хожу на спорт уже полгода и мне очень нравится: чистит мозги, рабочий перформанс лучше.Это перекликается с песней моего детства о пиратах из "Остров сокровищ", где говорилось, что в здоровом теле - здоровее дух. Ну и вообще, Джим молодец, потому что утром делает зарядку.Так вот. Тренер, которого, на самом деле, зовут Денис (я его называю "Тренер", как героя фильма "Джентельмены")... был на конференции мысленно (знал что она будет, видел фотки), и предложил больше тренироваться, чтобы выглядеть перформить лучше. После тренировки чувствуешь, что можешь свернуть горы. Не в первый день, конечно, так как в первый день хочется спать.Если кто из Нижнего Новгорода, сходите к Денису - он крутой тренер. Не жестит, осторожно и грамотно подходит к тренировкам, мотивирует.
    1,930видео1111521Открыть в Telegram
  • C# Heppard

    20 окт. 2025 г., 06:37изменён

    Function pointer #скоростьПредставим, что у нас есть подсистема вычисления. Один класс отвечает за выбор операции над значениями, а другой производит магию вычисления с использованием выбранной операции. В каждом из классов какая-то сложная логика, поэтому объединить их нельзя или сложно.Пример: операции над формулами в Excel - до того как мы прочитаем формулу, мы не знаем, какая операция будет произведена над ячейками.Условно, это выглядит вот так: MathOperation operation = SelectOperation(Context);Func<int, int, int> executor = operation switch { MathOperation.Add => MathOperations.Add, MathOperation.Subtract => MathOperations.Subtract, MathOperation.Multiply => MathOperations.Multiply, MathOperation.Divide => MathOperations.Divide, _ => Error.NotSupported(operation, Context) };Calculator.Execute(executor, xValue, yValue);Это работает быстро, но, благодаря "современному"
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
    2,2101512111Открыть в Telegram
  • C# Heppard

    13 окт. 2025 г., 15:03изменён

    Unsafe.SkipInit для структур #скоростьКак раз на конференции, в кулуарах, спрашивали про Unsafe.SkipInit. Набросал бенчмарк, который будет в комментариях.Как я уже говорил, это решение следующей проблемы: 1. Выделяется память. 2. Эта память заполняется дефолтными значениями (чтобы программист не получил в значениях полей структуры явную тарабарщину от предыдущих пользователей памяти). Условно 0000000000. 3. Память, в виде структуры, отдаётся пользователю (программисту). В классическом варианте, программист получит в числовом поле 0 (deafult), а в ссылочном - null.Вот Unsafe.SkipInit говорит, мол, господин рантайм, я и сам заполню все значения. Ну или, в смысле доклада, я и сам знаю какая область памяти мне нужна как инициализированная. То есть п.2 не выполняется. Что заметно улучшает скорость. Документация тут, там есть интересные примеры.Кстати, обратите внимание на разницу в
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
  • C# Heppard

    13 окт. 2025 г., 14:02изменён

    Сезон кода в Нижнем НовгородеОтвыступал на "Сезоне кода" (организатор Т-Банк). Я давно не ходил на конференции, давно не выступал. Мне очень понравилось. Хорошие темы, интересные спикеры.Участники конференции задавали много вопросов, затем обсуждение переместилось в кулуары. Это всегда очень здорово и приятно - побеседовать с коллегами, которые давно в теме доклада, которые смотрят на твои проблемы под другим углом, имеют свой опыт, свои решения. Супер.Ещё из плюсов конференции: трёхразовое питание, много активностей (от решений задач до карьерных консультаций) и афтерпати. Огромные экраны, просторный зал, отличная акустика и звук. Ух! Жаль, что не будет записей докладов - я бы хотел посидеть над некоторыми вдумчиво.Спасибо организаторам!Презентация тут.
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
    2,10014632Открыть в Telegram
  • C# Heppard

    7 июл. 2025 г., 19:33

    переслано из @are_you_teamlead

    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
    3,16044822Открыть в Telegram
  • C# Heppard

    27 июн. 2025 г., 11:34изменён

    Маленький словарь #скорость #памятьЧасто бывает, что мы получаем данные из внешнего источника или БД, создаём временный словарь, ищем по нему, а потом про него забываем. Часто бывает, что приходящих данных мало, например, 10-15 элементов.При этом, многие помнят, что поиск по словарю при небольшом количестве элементов не всегда эффективен (поиск по массиву будет быстрее). Также, те коллеги, которые помнят устройство Dictionary, могут вспомнить, что эта структура данных имеет два внутренних массива, выделение которых на горячих направлениях кода может вызвать неплохой memory pressure. Например, создание одного словаря размером в 10 элементов - почти 1кб памяти.В принципе, решение задачи лежит на поверхности.Необходимо создать такую структуру данных, которая бы с самого начала хранила данные в массиве, а, в случае большого количества элементов, переходила на честный словарь, чтобы
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
  • C# Heppard

    26 июн. 2025 г., 09:12изменён

    JsonPath в .NET #решениеПредставим себе, что есть сервис, который умеет получать данные из Kafka и складывать полученные данные в БД. Без программирования, просто декларативным указанием topic и таблицы в БД. То есть:1. Сервис работает по запросу (job или unit-of-work). 2. При создании job описывается маппинг данных из Kafka в нужную таблицу. 3. Описывается фильтрация и преобразовывает данных из Kafka так, как пользователю удобно. Ну чтобы не заниматься этим при каждом запросе в БД.То есть, во-первых, нужен вменяемый API, которым удобно пользоваться. Во-вторых, нужно описание маппинга полей сообщения из Kafka в поля Data-base-object (DBO). Ну и всякая фильтрация (например, отсечение удалённых), выбор определённых полей и некие операции над ними.Например, нам нужно взять подразделения компании, перенести часть нужных нам полей, а, также, налету, создать поле, в котором лежит
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
    2,44012431Открыть в Telegram
  • C# Heppard

    25 июн. 2025 г., 19:38изменён

    HasFlag #скоростьНедавно, как продвинутый, беседовал с Claude 4.0 Sonnet, который утверждал, что прямая битовая проверка (bitwise) наличия флага в enum быстрее, чем применение my_enum.HasFlag(flag). Я не поверил, так как проверял это пару лет назад, где-то в предоливьешные времена, после выхода .NET 5.Напомню, что enum может хранить как бы несколько значений, и может рассматриваться как битовое поле, то есть набор флагов. Например, тип оператора и его значение. Делается это просто, с помощью атрибута FlagsAttribute (пройдите по ссылке, там много полезной информации по использованию флагов в enum).[Flags] public enum Operator: short { None = 0x0,// Flags NonOperator = 0x0001, Comparison = 0x0002, ...// Comparison Operators Equals = 0x0700 | Comparison, NotEquals = 0x0800 | Comparison, ...
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
  • C# Heppard

    9 июн. 2025 г., 07:43

    287321Открыть в Telegram
  • C# Heppard

    4 июн. 2025 г., 09:45изменён

    IList as Span #скорость #памятьВ соседнем канале снова подняли вопрос по поводу разницы в скорости итерации по List<T> и IList<T>. Напомню, что я уже писал про это, но давно.Если кратко, то при итерации по IList возникает проблема с боксингом получаемого List<T>.Enumerator, так как он кастится к IEnumerator<T>. Это даёт 40 лишних байт аллокации. Также, вызов методов IEnumerator<T> приводит к поиску конкретной реализации по таблице виртуальных методов (callvirt в IL). Что, как не трудно догадаться, медленно, если существует более чем одна (это важно!) имплементация IEnumerator<T>.С тех пор, когда я про это писал, прошло много времени. Теперь я использую другой подход для случаев, когда коллеги используют IList, а мне ну уж очень надо выпендриться бежать по нему быстро.Этот метод есть в BCL, но является internal. Он весьма неплохо оптимизирован и используется, например, для
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
    3,3502410211Открыть в Telegram
  • C# Heppard

    23 мая 2025 г., 17:31изменён

    Быстрый код #отдых #философияОснователь компании id Software, гениальный и легендарный программист Джон Кармак признался, что вся современная индустрия компьютеров существует едва ли не благодаря не очень добросовестным программистам.В своем микроблоге в заблокированной в России американской соцсети Х (ранее Twitter) он написал, что миллиарды людей запросто могли бы работать на старых компьютерах и не тратить деньги на новые, если бы разработчики ставили в приоритет оптимизацию своего программного кода.Кармак открыто написал в своем микроблоге, что очень многие пользователи могли бы не тратить деньги на регулярное обновление ПК или покупку нового ноутбука."Большое количество пользователей по всему миру, чем многие могут себе представить, могли бы пользоваться устаревшим оборудованием, если бы оптимизация ПО на самом деле была приоритетом", – заявил создатель Doom.P.S.: Это
    3,1302566Открыть в Telegram
  • C# Heppard

    4 мая 2025 г., 10:08изменён

    StorageS3 0.6.4 #решение #хранилищеНа прошлой неделе выпустил новую версию библиотеки для экономного доступа к S3. Новая версия включает просьбы коллег по пробросу в библиотеку кастомного пула для массивов. Это было необходимо для случаев, когда стандартное поведение ArrayPool не устраивало.Также, добавлены исправления от других коллег, за что им большое спасибо!По традиции, обновил бенчмарки. Как оказалось, AWS (4.0.0) значительно улучшил производительность и потребление памяти. Minio тоже не стоит на месте, но всё ещё является не самой лучшей библиотекой для оптимального доступа к S3. Предыдущие замеры можно посмотреть тут.Новая версия уже в nuget.
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
  • C# Heppard

    3 мая 2025 г., 07:53

    переслано из @ai_driven

    А теперь, для любителей локальных моделей: Gemma 3 QATЧто-то мы все про проприетарщину да и проприетарщину. А что насчет локальных моделей? Надо сказать, что на этом поприще у маленькмх опенсорных моделей тоже наблюдается какой-то фантастический буст. Например, Gemma 3 27B в кодинге показывает результаты, сопоставимые с GPT-4o-mini. А из ризонинг моделей, как упоминал ранее, QwQ 32B на уровне Claude 3.7 Sonnet Thinking, а DeepCoder 14B (это новая спец. моделька от создателей DeepSeek) на уровне o3-mini (low). Ну, и опять эксклюзив - на агентских задачах по кодингу, неожиданно вырвалась вперед моделька OpenHands LM 32B от ребят из OpenHands, которые дотренировали ее из Qwen Coder 2.5 Instruct 32B на своем "тренажере для агентов" SWE-Gym, опередив в итоге в SWE-bench даже огромную Deepseek V3 0324. В общем, OpenHands молодцы! Кстати, недавно их Code-агент взял новую соту (SoTA - State
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# HeppardИллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
  • C# Heppard

    3 апр. 2025 г., 08:13изменён

    Случайная строка из 12 символов #отдыхНедавно я снова упражнялся с роботами (LLM, GPT). Мне сказали, что они стали значительно умнее за последние 6 месяцев. Действительно, беседы на темы, где я не специалист выглядели весьма убедительно. Роботы стали предлагать более умные решения, исправляться и уточнять, если меня что-то не устраивает, признавать ошибки и предлагать альтернативные варианты.При этом, конечно, в областях, где я специалист, всё по прежнему не очень радужно. Так, простая задача по созданию случайной строки (random string) всё ещё решается в стиле "посмотреть на stackoverflow и предложить самый популярный вариант". Роботы прямо предлагали решения из вот этой вот темы.const string chars = "чарики"; return new string(Enumerable .Repeat(chars, length) .Select(s => s[random.Next(s.Length)]) .ToArray());Это решение мягко говоря сомнительное и не оптимальное (см. Linq в
    Иллюстрация к посту канала C# HeppardИллюстрация к посту канала C# Heppard
    2,78015443Открыть в Telegram