ИИ впечатляет всё больше и больше
Последние несколько дней я занимаюсь миграцией своего блога с Jekyll на Astro, и в этом мне очень помогает ИИ.
1. Частично пишу код с помощью ИИ-агентов в GitHub Copilot (тот самый Vibe Coding). Особенно полезно, когда нужно выполнить много рутинных задач: заменить <img/> на <Image>, добавить краткие описания ко всем постам, отредактировать теги и привести их к единому стилю.
2. В Astro у каждого поста должна быть обложка, тогда как в Jekyll она была не обязательной. Здесь на помощь приходит генерация картинок в ChatGPT. Впечатляет, что нейросети уже умеют корректно генерировать текст.
Последние несколько дней я занимаюсь миграцией своего блога с Jekyll на Astro, и в этом мне очень помогает ИИ.
1. Частично пишу код с помощью ИИ-агентов в GitHub Copilot (тот самый Vibe Coding). Особенно полезно, когда нужно выполнить много рутинных задач: заменить <img/> на <Image>, добавить краткие описания ко всем постам, отредактировать теги и привести их к единому стилю.
2. В Astro у каждого поста должна быть обложка, тогда как в Jekyll она была не обязательной. Здесь на помощь приходит генерация картинок в ChatGPT. Впечатляет, что нейросети уже умеют корректно генерировать текст.
Утиная типизация в C#
English version.
Думаю, опытные C#-разработчики знают ответ на вопрос: «Что нужно сделать, чтобы можно было перечислить объекты при помощи foreach?»
Для этого не обязательно наследовать класс от интерфейса IEnumerable. Достаточно, чтобы класс имел публичный метод GetEnumerator, который возвращает объект, реализующий IEnumerator.
Такое поведение иногда называют утиной типизацией — компилятору неважно, реализует ли класс интерфейс IEnumerable или нет. Главное, чтобы в нём был метод, возвращающий перечислитель.
Аналогичное поведение встречается и при работе с async-await. Чтобы «ожидать» тип, достаточно, чтобы у него был метод GetAwaiter(), возвращающий тип TaskAwaiter или ValueTaskAwaiter. При этом даже не обязательно, чтобы этот метод был внутри самого ожидаемого типа.
Недавно я наткнулся на ещё один случай, который можно считать примером утиной типизации. Начиная с версии 12, в C# появился упрощённый способ инициализации коллекций:
Этот лаконичный синтаксис работает не со всеми коллекциями. Например, следующий код не скомпилируется:
Компилятор ожидает, что у типа коллекции будет метод Add, но в Queue вместо него используется Enqueue, а в Stack — Push. Изменить эти типы мы не можем, поэтому можно сделать следующий финт и помочь компилятору обнаружить метод Add:
Упрощённая инициализация работает и с кастомными коллекциями, при условии, что для них есть соответствующий метод Add — неважно, внутри типа или в методе-расширении.
UPD: В комментариях выяснили, что оператор using может быть использован с ref struct без IDisposable начиная с C# 8.0.
UPD2: В комментариях выяснили, что foreach может обойтись без IEnumerator.
English version.
Думаю, опытные C#-разработчики знают ответ на вопрос: «Что нужно сделать, чтобы можно было перечислить объекты при помощи foreach?»
Для этого не обязательно наследовать класс от интерфейса IEnumerable. Достаточно, чтобы класс имел публичный метод GetEnumerator, который возвращает объект, реализующий IEnumerator.
// Этот код компилируется
var obj = new MyType();
foreach (var item in obj);
class MyType {
public IEnumerator GetEnumerator() {
throw new Exception();
}
}
Такое поведение иногда называют утиной типизацией — компилятору неважно, реализует ли класс интерфейс IEnumerable или нет. Главное, чтобы в нём был метод, возвращающий перечислитель.
Аналогичное поведение встречается и при работе с async-await. Чтобы «ожидать» тип, достаточно, чтобы у него был метод GetAwaiter(), возвращающий тип TaskAwaiter или ValueTaskAwaiter. При этом даже не обязательно, чтобы этот метод был внутри самого ожидаемого типа.
cs
// Этот код тоже компилируется
var obj = new MyType();
await obj;
class MyType {
}
static class MyTypeExtensions {
public static TaskAwaiter GetAwaiter(
this MyType @object) {
throw new Exception();
}
}
Недавно я наткнулся на ещё один случай, который можно считать примером утиной типизации. Начиная с версии 12, в C# появился упрощённый способ инициализации коллекций:
int[] array = [1, 2, 3, 4, 5];
List<int> list = [1, 2, 3, 4, 5];
Этот лаконичный синтаксис работает не со всеми коллекциями. Например, следующий код не скомпилируется:
Queue<int> queue = [1, 2, 3, 4, 5];
Stack<int> stack = [1, 2, 3, 4, 5];
Компилятор ожидает, что у типа коллекции будет метод Add, но в Queue вместо него используется Enqueue, а в Stack — Push. Изменить эти типы мы не можем, поэтому можно сделать следующий финт и помочь компилятору обнаружить метод Add:
public static class CollectionExtensions {
public static void Add<T>(
this Queue<T> collection,
T item) => collection.Enqueue(item);
public static void Add<T>(
this Stack<T> collection,
T item) => collection.Push(item);
}
Упрощённая инициализация работает и с кастомными коллекциями, при условии, что для них есть соответствующий метод Add — неважно, внутри типа или в методе-расширении.
// и этот код компилируется
MyType collection = [1, 2, 3];
class MyType : IEnumerable {
public IEnumerator GetEnumerator() {
throw new Exception();
}
}
static class MyTypeExtensions {
public static void Add(
this MyType o,
int value) { }
}
UPD: В комментариях выяснили, что оператор using может быть использован с ref struct без IDisposable начиная с C# 8.0.
using var obj = new MyType();
ref struct MyType {
public void Dispose() { }
}
UPD2: В комментариях выяснили, что foreach может обойтись без IEnumerator.
// Этот код компилируется
var obj = new MyType();
foreach (var item in obj);
class MyType {
public MyEnumerator GetEnumerator() => new();
}
class MyEnumerator {
public object Current => new();
public bool MoveNext() => false;
}
Ещё больше опенсорсных проектов становятся платными
Две свежие новости из мира open-source software (OSS) в .NET:
1. MassTransit станет платным, начиная с версии 9. Новая версия будет распространяться по коммерческой лицензии. При этом версия 8 останется OSS и будет получать только критические патчи и багфиксы.
2. Джимми Богарт, автор AutoMapper и MediatR, также сообщил, что переводит свои проекты на коммерческую модель. Он больше не может поддерживать их в свободное от работы время, как раньше, и хочет создать устойчивую модель развития. Конкретные детали монетизации пока не объявлены. Забавно, что всего 2 месяца назад он писал, что никогда не сделает MediatR платным.
Что происходит?
Не сказать, что я большой фанат AutoMapper и MediatR. По-моему, от них даже больше проблем, чем пользы. Но поддержка OSS – действительно сложная штука. Людей, которые тратят личное время на такие проекты можно понять. Я это вижу даже по EventFlow. У библиотеки 2.4 тыс. звёзд на GitHub и миллионы загрузок на NuGet. Но при этом автор пишет, что почти нет пул-реквестов от компаний, не говоря уже о финансовой поддержке.
Можно вспомнить свежий случай с FluentAssertions. Ещё 2 года назад автор с иронией «хвастался», что кто-то задонатил $31. Неудивительно, что он решил продать своё детище компании. Правда это не отменяет текущий неадекватный ценник на библиотеку – сейчас она стоит почти как Rider.
Также можно привести в пример Avalonia UI. У проекта 27.3 тыс. звёзд на GitHub, десятки миллионов загрузок на NuGet и всего 43 спонсора. Даже если предположить, что каждый из них донатит по $100 в месяц (что маловероятно), это всего $4300 — немного для команды из 11 человек. Да, они наверняка дополнительно зарабатывают на консалтинге, но если говорить исключительно о добровольной поддержке через донаты — ситуация грустная.
Короче говоря, заниматься OSS — это интересно, полезно и вдохновляюще. Но когда проект становится популярным, трудно продолжать работать над ним бесплатно с учётом возрастающей нагрузки. В какой-то момент разработчик выгорает и начинает хотеть справедливой компенсации за свой труд. И вместо поддержки часто получает волну критики, причём от своих же коллег по цеху.
В итоге от всей этой ситуации выигрывают только корпорации. Одни просто используют OSS в своих коммерческих продуктах. Другие скупают права на библиотеки, фактически присваивая результат многолетнего труда десятков разработчиков, которые вкладывали в проект своё время, знания и энтузиазм.
Две свежие новости из мира open-source software (OSS) в .NET:
1. MassTransit станет платным, начиная с версии 9. Новая версия будет распространяться по коммерческой лицензии. При этом версия 8 останется OSS и будет получать только критические патчи и багфиксы.
2. Джимми Богарт, автор AutoMapper и MediatR, также сообщил, что переводит свои проекты на коммерческую модель. Он больше не может поддерживать их в свободное от работы время, как раньше, и хочет создать устойчивую модель развития. Конкретные детали монетизации пока не объявлены. Забавно, что всего 2 месяца назад он писал, что никогда не сделает MediatR платным.
Что происходит?
Не сказать, что я большой фанат AutoMapper и MediatR. По-моему, от них даже больше проблем, чем пользы. Но поддержка OSS – действительно сложная штука. Людей, которые тратят личное время на такие проекты можно понять. Я это вижу даже по EventFlow. У библиотеки 2.4 тыс. звёзд на GitHub и миллионы загрузок на NuGet. Но при этом автор пишет, что почти нет пул-реквестов от компаний, не говоря уже о финансовой поддержке.
Можно вспомнить свежий случай с FluentAssertions. Ещё 2 года назад автор с иронией «хвастался», что кто-то задонатил $31. Неудивительно, что он решил продать своё детище компании. Правда это не отменяет текущий неадекватный ценник на библиотеку – сейчас она стоит почти как Rider.
Также можно привести в пример Avalonia UI. У проекта 27.3 тыс. звёзд на GitHub, десятки миллионов загрузок на NuGet и всего 43 спонсора. Даже если предположить, что каждый из них донатит по $100 в месяц (что маловероятно), это всего $4300 — немного для команды из 11 человек. Да, они наверняка дополнительно зарабатывают на консалтинге, но если говорить исключительно о добровольной поддержке через донаты — ситуация грустная.
Короче говоря, заниматься OSS — это интересно, полезно и вдохновляюще. Но когда проект становится популярным, трудно продолжать работать над ним бесплатно с учётом возрастающей нагрузки. В какой-то момент разработчик выгорает и начинает хотеть справедливой компенсации за свой труд. И вместо поддержки часто получает волну критики, причём от своих же коллег по цеху.
В итоге от всей этой ситуации выигрывают только корпорации. Одни просто используют OSS в своих коммерческих продуктах. Другие скупают права на библиотеки, фактически присваивая результат многолетнего труда десятков разработчиков, которые вкладывали в проект своё время, знания и энтузиазм.
Коллеги, посоветуйте, пожалуйста, бесплатные Postgres-as-a-Service решения.
Цены у облачных провайдеров совсем не подходят для pet-проектов. Например, тот же Яндекс стоит больше 5000 рублей / месяц.
Основные требования:
- Бесплатно навсегда, без триал периода.
- Наличие резервных копий с возможностью восстановления хотя бы за последние 1–3 дня.
- Без обязательной привязки банковской карты.
- Локация — Европа.
- Объём — достаточно пары сотен мегабайт.
Google Sheets не предлагать. Я уже использую её в качестве базы данных.
Цены у облачных провайдеров совсем не подходят для pet-проектов. Например, тот же Яндекс стоит больше 5000 рублей / месяц.
Основные требования:
- Бесплатно навсегда, без триал периода.
- Наличие резервных копий с возможностью восстановления хотя бы за последние 1–3 дня.
- Без обязательной привязки банковской карты.
- Локация — Европа.
- Объём — достаточно пары сотен мегабайт.
SharpLab мёртв?
Сегодня буднично писал код. В какой-то момент мне понадобилось быстро вспомнить работу одной коллекции. Для таких случаях я обычно использую sharplab.io.
Открыв сайт и начав писать код я понял, что пользоваться им очень трудно из-за раздражающего бага: при вводе всплывает окно автокомплита, и если нажать Tab или Enter, редактор просто удаляет весь текст.
Я пошёл проверить, открыт ли issue. Оказалось, что да — и уже почти три месяца. Но никто его не правит, а пул реквесты в репозиторий вообще не принимаются.
Последняя активность в проекте — 18 ноября 2024 года. С тех пор — тишина.
На всякий случай я открыл issue с вопросом. Посмотрим, что ответит Андрей (автор SharpLab) и будет ли вообще ответ.
Сегодня буднично писал код. В какой-то момент мне понадобилось быстро вспомнить работу одной коллекции. Для таких случаях я обычно использую sharplab.io.
Открыв сайт и начав писать код я понял, что пользоваться им очень трудно из-за раздражающего бага: при вводе всплывает окно автокомплита, и если нажать Tab или Enter, редактор просто удаляет весь текст.
Я пошёл проверить, открыт ли issue. Оказалось, что да — и уже почти три месяца. Но никто его не правит, а пул реквесты в репозиторий вообще не принимаются.
Последняя активность в проекте — 18 ноября 2024 года. С тех пор — тишина.
На всякий случай я открыл issue с вопросом. Посмотрим, что ответит Андрей (автор SharpLab) и будет ли вообще ответ.
Альтернативы SharpLab
В продолжение вчерашнего поста публикую список инструментов, которые могут служить заменой SharpLab.
👩💻 C# Interactive в Visual Studio — встроенный REPL, который запускается через меню View → Other Windows → C# Interactive. Позволяет писать и выполнять C# код в отдельном окне.
👩💻 C# Interactive в Rider — аналогичный инструмент от JetBrains.
👩💻 csharprepl — опенсорсная REPL-утилита. Устанавливается через .NET CLI:
👩💻 dotnet-repl — ещё одна опенсорсная REPL-утилита. Также устанавливается через .NET CLI:
👩💻 Polyglot Notebook — расширение для VS Code. Использовать очень просто: установить, создать .dib файл, выбрать С# и можно писать код. Функционал аналогичен Jupiter Notebook.
⚙️ LINQPad — старая добрая десктопная программа, которая, пожалуй, больше всего по внешнему виду и функционалу похожа на SharpLab. Работает только на Windows и Mac (бета). К сожалению, полноценный функционал доступен только в платной версии, поэтому не очень подходит для рабочей тачки.
🌐 Compiler Explorer — онлайн дизассемблер. Позволяет просматривать только ASM. Поддерживает множество языков и C#, в том числе.
👩💻 dotPeek — бесплатный декомпайлер от JetBrains. Удобен тем, что позволяет смотреть C#, IL и ASM в одном окне. Работает только на Windows.
За рекомендации спасибо @ishvedov и @NSent.
В продолжение вчерашнего поста публикую список инструментов, которые могут служить заменой SharpLab.
dotnet tool install -g csharprepl
. Есть автокомплит, Intellisense, подсветка синтаксиса, просмотр IL-кода и даже поддержка OpenAI через Bring Your Own Token. Примеры использования можно посмотреть в репозитории.dotnet tool install -g dotnet-repl
. По сравнению с csharprepl, хуже работает подсветка синтаксиса. Совсем нет автокомплита, Intellisense и других фичей.⚙️ LINQPad — старая добрая десктопная программа, которая, пожалуй, больше всего по внешнему виду и функционалу похожа на SharpLab. Работает только на Windows и Mac (бета). К сожалению, полноценный функционал доступен только в платной версии, поэтому не очень подходит для рабочей тачки.
🌐 Compiler Explorer — онлайн дизассемблер. Позволяет просматривать только ASM. Поддерживает множество языков и C#, в том числе.
За рекомендации спасибо @ishvedov и @NSent.
Please open Telegram to view this post
VIEW IN TELEGRAM
В продолжение своего вопроса собрал список провайдеров, которые предоставляют бесплатный хостинг PostgreSQL.
В таблице сравнение по лимитам, доступным регионам, бэкапам и другим параметрам. Все сервисы соответствуют критериям:
- Бесплатная регистрация без банковской карты.
- Нет лимита по времени, то есть используемая база данных не будет удалена через определённый промежуток времени.
Везде зарегистрировался и проверил сам.
Please open Telegram to view this post
VIEW IN TELEGRAM
Месяц назад выкладывал статистику с hh.ru. С тех пор продолжаю следить — ежедневно фиксирую количество вакансий в разных разрезах. Вот что есть интересного:
🔹 Самый «вакансийный» день — среда. Затем вторник и четверг. Меньше всего предложений по понедельникам и в выходные. Почему так я не знаю. Может, дело в алгоритмах hh или привычки HR-ов.
🔹 Количество вакансий колеблется в пределах от 2337 до 2544. Разброс небольшой, но есть.
🔹 За месяц — минус 3%. Это разница между медианным количеством вакансий в первую и последнюю неделю наблюдений. Выводы никакие не делаю, т.к. причин может быть множество. Нужно наблюдать.
🔹 С зарплатами без изменений. 48% вакансий с зарплатой предлагают до ₽150к. До ₽400к попадают 95% вакансий.
🔹 С удалёнкой тоже все стабильно: 36%.
Если интересно — продолжу делиться наблюдениями.
Please open Telegram to view this post
VIEW IN TELEGRAM
Если коротко — мне не понравилось. Слишком много шума и мало пользы. Даже простые баги редко удаётся исправить. Агенты бесконечно генерируют тонны кода, который не работает.
Лучше всего показала себя связка Ask + Edits с ручной проверкой. Например, так я использую её для поиска и исправления багов:
1. Указываю один или несколько проектов, где, предположительно, есть баг.
2. Включаю режим Ask и прошу проанализировать код, найти и объяснить возможное место ошибки.
3. ИИ предлагает участок кода и объясняет, в чём может быть проблема.
4. Проверяю, действительно ли там может быть баг.
5. Если да, то переключаюсь на режим Edits и пишу: «теперь исправь баг». Благодаря общему контексту, Edits использует объяснение из Ask.
6. Жду результата и проверяю. Если не сработало — возвращаюсь к шагу 1.
Делитесь своим опытом использования ИИ. 👇
Please open Telegram to view this post
VIEW IN TELEGRAM
Влияние логирования в C# на производительность
English version.
Давно ничего не было про производительность. Сегодня про логирование и как оно влияет на производительность.
Если вы писали такой код:
...то, скорее всего замечали, что IDE настойчиво рекомендовала так больше не делать.
Почему? Потому что интерполированные строки — это синтаксический сахар.
После компиляции код будет выглядеть так:
Проблема здесь в том, что строка text создаётся всегда, даже если уровень логирования выше Debug и сообщение в лог не попадёт.
Более правильный вариант логирования выглядит так:
В этом случае строковый шаблон "Request Id: {Id} finished with Error: {Error}" не будет использоваться, если, например, минимальный уровень логирования Information.
Лишних аллокаций удастся избежать… так я думал, пока не написал бенчмарки и не проверил результаты.
Читать полностью на сайте 👇🏻
P.S. Зацените обновлённый блог. Наконец-то закончил миграцию с Jekyll на Astro.
English version.
Давно ничего не было про производительность. Сегодня про логирование и как оно влияет на производительность.
Если вы писали такой код:
// CA2254: The logging message template
// should not vary between calls
logger.LogDebug($"Request Id: {id} finished with Error: {error}");
...то, скорее всего замечали, что IDE настойчиво рекомендовала так больше не делать.
Почему? Потому что интерполированные строки — это синтаксический сахар.
После компиляции код будет выглядеть так:
var handler = new DefaultInterpolatedStringHandler(34, 2);
handler.AppendLiteral("Request Id: ");
handler.AppendFormatted(value);
handler.AppendLiteral(" finished with Error: ");
handler.AppendFormatted(value2);
string text = handler.ToStringAndClear();
logger.LogDebug(text);
Проблема здесь в том, что строка text создаётся всегда, даже если уровень логирования выше Debug и сообщение в лог не попадёт.
Более правильный вариант логирования выглядит так:
logger.LogDebug("Request Id: {Id} finished with Error: {Error}", Id, Error);
В этом случае строковый шаблон "Request Id: {Id} finished with Error: {Error}" не будет использоваться, если, например, минимальный уровень логирования Information.
Лишних аллокаций удастся избежать… так я думал, пока не написал бенчмарки и не проверил результаты.
Читать полностью на сайте 👇🏻
www.alexeyfv.xyz
Влияние логирования в C# на производительность
Как логирование в C# влияет на производительность приложения. Сравнение интерполяции строк, шаблонов и LoggerMessageAttribute.
xxHash: самый быстрый алгоритм хеширования в экосистеме .NET
Читать на сайте.
Read on website.
Недавно на работе возникла задача: нужно было посчитать стабильный хэш объектов. Я сразу подумал про стандартные криптографические алгоритмы вроде SHA1, SHA256, SHA512 и MD5. Но у них есть два недостатка:
1. Хэш получается большим — от 160 до 512 бит.
2. Возвращается массив байтов, что означает лишние аллокации памяти.
Это подтолкнуло меня к поиску альтернатив. Так я быстро наткнулся на репозиторий xxHash и его реализацию на C#. Отличие xxHash в высокой скорости и возможности получить хэш в виде целого числа.
Важно понимать, что xxHash не криптографический алгоритм — он предназначен для других задач: быстрого хэширования, сравнения данных, создания ключей для кэшей или индексов.
Реализации в .NET
Для использования xxHash в своём приложении нужно установить пакет System.IO.Hashing. В нём есть 4 реализации алгоритма xxHash:
- XxHash32 (32 бита);
- XxHash64 (64 бита);
- XxHash3 (64 бита);
- XxHash128 (128 бит).
Производительность
Я сравнил эти алгоритмы по скорости расчёта хэша между собой. К сравнению также добавил алгоритмы SHA1, SHA2, SHA3 и MD5. Результаты оказались ожидаемыми (на обложке) — xxHash значительно быстрее остальных.
Пример использования
xxHash особенно удобен благодаря следующим фишкам:
– Метод
– Хэш в виде числа. В зависимости от алгоритма можно получить хэш как
– Поддержка работы со
Пример реализации расчёта хэша с xxHash на второй картинке.
Выводы
Использование xxHash для расчёта стабильного хэша позволяет:
– Быстро рассчитать хэш. Это один из самых быстрых алгоритмов.
– Избежать аллокаций. Используя
– Хранить хэш как
Читать на сайте.
Read on website.
Недавно на работе возникла задача: нужно было посчитать стабильный хэш объектов. Я сразу подумал про стандартные криптографические алгоритмы вроде SHA1, SHA256, SHA512 и MD5. Но у них есть два недостатка:
1. Хэш получается большим — от 160 до 512 бит.
2. Возвращается массив байтов, что означает лишние аллокации памяти.
Это подтолкнуло меня к поиску альтернатив. Так я быстро наткнулся на репозиторий xxHash и его реализацию на C#. Отличие xxHash в высокой скорости и возможности получить хэш в виде целого числа.
Важно понимать, что xxHash не криптографический алгоритм — он предназначен для других задач: быстрого хэширования, сравнения данных, создания ключей для кэшей или индексов.
Реализации в .NET
Для использования xxHash в своём приложении нужно установить пакет System.IO.Hashing. В нём есть 4 реализации алгоритма xxHash:
- XxHash32 (32 бита);
- XxHash64 (64 бита);
- XxHash3 (64 бита);
- XxHash128 (128 бит).
Производительность
Я сравнил эти алгоритмы по скорости расчёта хэша между собой. К сравнению также добавил алгоритмы SHA1, SHA2, SHA3 и MD5. Результаты оказались ожидаемыми (на обложке) — xxHash значительно быстрее остальных.
Пример использования
xxHash особенно удобен благодаря следующим фишкам:
– Метод
Append
. Он позволяет поэтапно добавлять данные к расчёту хэша без промежуточных аллокаций. – Хэш в виде числа. В зависимости от алгоритма можно получить хэш как
uint
, ulong
или UInt128
, без массива байтов. – Поддержка работы со
Span<T>
. Можно использовать стек вместо кучи и избежать лишних аллокаций.Пример реализации расчёта хэша с xxHash на второй картинке.
Выводы
Использование xxHash для расчёта стабильного хэша позволяет:
– Быстро рассчитать хэш. Это один из самых быстрых алгоритмов.
– Избежать аллокаций. Используя
Span
и Append
, можно рассчитывать хэш, используя только стек и регистры.– Хранить хэш как
uint
или ulong
. Это всего 4 и 8 байт соответственно. Такие значения хорошо индексируются БД и позволяют упростить структуру SQL запросов. Вместо сложных запросов с множеством условий, можно искать по одному полю: WHERE Hash = ...
Это особенно полезно при работе с таблицами, где сотни миллионов строк.В продолжение вчерашнего поста про xxHash
Коллеги в комментариях подсказали ещё один интересный алгоритм — GxHash. Я посмотрел репозиторий вчера вечером и быстро прогнал бенчмарк (результаты на обложке).
Что понравилось:
– Действительно быстрый. Даже быстрее xxHash.
– Как и xxHash, возвращает хэш в виде uint, ulong или UInt128.
Недостатки:
– Нет NuGet-пакета. Пришлось копировать исходники вручную.
Спасибо за наводку @NSent
UPD: @viruseg нашёл NuGet-пакет. Большое спасибо.
Коллеги в комментариях подсказали ещё один интересный алгоритм — GxHash. Я посмотрел репозиторий вчера вечером и быстро прогнал бенчмарк (результаты на обложке).
Что понравилось:
– Действительно быстрый. Даже быстрее xxHash.
– Как и xxHash, возвращает хэш в виде uint, ulong или UInt128.
– Нет NuGet-пакета. Пришлось копировать исходники вручную.
Спасибо за наводку @NSent
UPD: @viruseg нашёл NuGet-пакет. Большое спасибо.
Используйте индексаторы вместо методов LINQ
Это часть серии, в которой я разбираю правила качества кода .NET с точки зрения производительности. Сегодня поговорим про CA1826: Use property instead of Linq Enumerable method.
Описание правила
Правило рекомендует не использовать методы First(), Last(), Count() из LINQ с IReadOnlyList<T>:
Вместо этого стоит использовать индексатор или свойство Count:
Анализ производительности
Я написал простой бенчмарк, чтобы проверить, насколько LINQ действительно влияет на производительность. Результаты в репозитории и на диаграмме.
Как видно, разница есть. Но она совсем небольшая — всего несколько микросекунд на моём ноутбуке.
Стоит ли заморачиваться?
В большинстве случаев нет. Прирост производительности минимальный. Но если вы пишете высокопроизводительный код или используете LINQ методы в цикле — возможно код стоит отрефакторить.
Это часть серии, в которой я разбираю правила качества кода .NET с точки зрения производительности. Сегодня поговорим про CA1826: Use property instead of Linq Enumerable method.
Описание правила
Правило рекомендует не использовать методы First(), Last(), Count() из LINQ с IReadOnlyList<T>:
IReadOnlyList<string> list = ["str1", "str2", "str3"];
var first = list.First(); // CA1826
var last = list.Last(); // CA1826
var count = list.Count(); // CA1826
Вместо этого стоит использовать индексатор или свойство Count:
IReadOnlyList<string> list = ["str1", "str2", "str3"];
var first = list[0];
var last = list[^1];
var count = list.Count;
Анализ производительности
Я написал простой бенчмарк, чтобы проверить, насколько LINQ действительно влияет на производительность. Результаты в репозитории и на диаграмме.
Как видно, разница есть. Но она совсем небольшая — всего несколько микросекунд на моём ноутбуке.
Стоит ли заморачиваться?
В большинстве случаев нет. Прирост производительности минимальный. Но если вы пишете высокопроизводительный код или используете LINQ методы в цикле — возможно код стоит отрефакторить.
Скриптинг на C# всё ближе
Microsoft продолжает двигаться в сторону упрощения C#. В свежем видео они показали функционал, позволяющий запускать cs-файлы без sln и csproj. Фича доступна в Preview версии .NET 10.
Пример:
Работает даже с NuGet-пакетами прямо в файле:
Как выглядит результат - на скриншоте.
Пока не совсем ясно, будет ли возможность запускать такие файлы в Docker, то есть через Runtime, а не через SDK.
Microsoft продолжает двигаться в сторону упрощения C#. В свежем видео они показали функционал, позволяющий запускать cs-файлы без sln и csproj. Фича доступна в Preview версии .NET 10.
Пример:
dotnet run hello.cs
Работает даже с NuGet-пакетами прямо в файле:
#:package Spectre.Console@0.50
#:package Spectre.Console.Cli@0.50
using Spectre.Console;
AnsiConsole.Markup("[underline red]Hello[/] [underline green]World![/]");
Как выглядит результат - на скриншоте.
Пока не совсем ясно, будет ли возможность запускать такие файлы в Docker, то есть через Runtime, а не через SDK.
StringBuilder: избегайте ToString при использовании Append
Read on website.
Читать на сайте.
Это новая часть серии, в которой я разбираю правила качества кода .NET с точки зрения производительности. Сегодня поговорим про CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder.
Описание правила
Правило рекомендует не преобразовывать значения в строку при вызове методов Append или Insert.
Вместо этого лучше передать значение напрямую:
Это правило касается примитивных типов вроде byte, short, int, double, long и других.
Анализ производительности
Я написал простой бенчмарк, чтобы оценить, насколько эти подходы отличаются по производительности. Результаты в репозитории и на диаграмме.
Разница по времени — небольшая: около 5 микросекунд на моём ноутбуке. Разница по памяти более заметная: около 20 кБ.
Как работает эта оптимизация?
Когда вы используете метод Append(int), под капотом StringBuilder вызываются методы AppendSpanFormattable<T> и InsertSpanFormattable<T>.
Например, упрощённая версия AppendSpanFormattable<T> выглядит так:
Этот метод использует интерфейс ISpanFormattable.TryFormat, чтобы записать значение напрямую во внутренний буфер StringBuilder как Span<char>. Это позволяет: избежать аллокации строки; упаковки (boxing) и вызова виртуального метода ToString().
Стоит ли заморачиваться?
Скорее да. Даже если не брать в расчёт прирост производительности, такой код:
и выглядит проще и чище, чем:
И в качестве бонуса, он работает быстрее и потребляет меньше памяти. Win-win.
Read on website.
Читать на сайте.
Это новая часть серии, в которой я разбираю правила качества кода .NET с точки зрения производительности. Сегодня поговорим про CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder.
Описание правила
Правило рекомендует не преобразовывать значения в строку при вызове методов Append или Insert.
var i = 123;
var sb = new StringBuilder();
sb.Append(i.ToString()); // CA1830
Вместо этого лучше передать значение напрямую:
var i = 123;
var sb = new StringBuilder();
sb.Append(i);
Это правило касается примитивных типов вроде byte, short, int, double, long и других.
Анализ производительности
Я написал простой бенчмарк, чтобы оценить, насколько эти подходы отличаются по производительности. Результаты в репозитории и на диаграмме.
Разница по времени — небольшая: около 5 микросекунд на моём ноутбуке. Разница по памяти более заметная: около 20 кБ.
Как работает эта оптимизация?
Когда вы используете метод Append(int), под капотом StringBuilder вызываются методы AppendSpanFormattable<T> и InsertSpanFormattable<T>.
Например, упрощённая версия AppendSpanFormattable<T> выглядит так:
private StringBuilder AppendSpanFormattable<T>(T value) where T : ISpanFormattable
{
if (value.TryFormat(
RemainingCurrentChunk,
out int charsWritten,
format: default,
provider: null))
{
m_ChunkLength += charsWritten;
return this;
}
return Append(value.ToString());
}
Этот метод использует интерфейс ISpanFormattable.TryFormat, чтобы записать значение напрямую во внутренний буфер StringBuilder как Span<char>. Это позволяет: избежать аллокации строки; упаковки (boxing) и вызова виртуального метода ToString().
Стоит ли заморачиваться?
Скорее да. Даже если не брать в расчёт прирост производительности, такой код:
sb.Append(i);
и выглядит проще и чище, чем:
sb.Append(i.ToString());
И в качестве бонуса, он работает быстрее и потребляет меньше памяти. Win-win.
Два месяца назад публиковал список бесплатных сервисов PostgreSQL. Напомню, что это список провайдеров, которые предоставляют бесплатный хостинг PostgreSQL и соответствуют следующим критериям:
- Бесплатная регистрация без банковской карты.
- Нет лимита по времени, то есть используемая база данных не будет удалена через определённый промежуток времени.
За это время проект получил 23 звезды и 1 пул реквест. Два сервиса были удалены из списка, и два новых добавлены.
✅ Новые сервисы
Xata.io Lite – предоставляет бесплатный тариф с 15 ГБ и ежедневными бэкапами.
Rapidapp.io – бесплатный план с 20 МБ хранилища.
❌ Удалённые сервисы
Tembo.io – отменили бесплатный план с 30 мая. Жалко, т.к., на мой взгляд, у этого провайдера были самые адекватные условия.
Turso.tech – удалён, так как это SQLite as a Service, а не PostgreSQL (добавил по ошибке).
Please open Telegram to view this post
VIEW IN TELEGRAM