Вышел .NET 7, а это значит, что можно вдоволь насладиться различными нововведениями и фишками. Расскажем про самые интересные улучшения: C# 11, контейнеры, производительность, GC и прочее.
Мы уже выпустили статью, посвящённую разбору нововведений в C# 11. В ней мы прошлись по новым особенностям: обобщённой математике, исходным строкам, модификатору required, параметрам типа в атрибутах и прочему.
Кстати, мы уже работаем над поддержкой .NET 7 и C# 11 — она будет добавлена в PVS-Studio 7.22. Релиз запланирован на начало декабря, а загрузить свежую версию анализатора можно будет здесь. Если хотите попробовать бету уже сейчас, напишите нам :).
AOT (ahead-of-time) – компиляция приложения не в промежуточный, а сразу в машинный код. Native AOT использует ahead of time компилятор для компиляции IL в машинный код во время публикации self-contained приложения. Native AOT был переведён из статуса экспериментального. Основными преимуществами native AOT приложений являются:
Native AOT приложения имеют ряд ограничений:
В .NET существует такое понятие, как многоуровневая компиляция (Tiered Compilation). Если говорить простым языком, то многоуровневая компиляция снижает время запуска приложения. Как? Изначально JIT будет генерировать плохо оптимизированный машинный код (tier-0) для методов, т. к. это просто требует меньше времени. Если же количество вызовов метода переступает за определённый порог, то JIT cгенерирует для этого метода более оптимизированный код (tier-1). Данный подход не работает, например, с циклами, т. к. это может приводить к ухудшению производительности. К слову, на данный момент существует всего два уровня.
OSR позволяет заменять машинный код, который выполняется в данный момент, на новый — более оптимизированный. Ранее такая возможность была только между вызовами метода. Подобный подход позволяет применять многоуровневую компиляцию ко всем методам. Благодаря этому можно добиться более быстрой компиляции и при этом стабильной производительности. Судя по тестам Microsoft, внедрение данной технологии помогло на 25 % ускорить запуск нагруженных приложений. OSR в .NET 7 включена по умолчанию для x64 и Arm64.
Управление зависимостями для многопроектных решений может оказаться сложной задачкой. Теперь же в ситуациях, когда требуется управление общими зависимостями для нескольких проектов, вы можете использовать централизованное управление NuGet пакетами. Для централизованного управления зависимостями потребуется добавить файл Directory.Packages.props в корень решения. Благодаря CPM версия пакета указывается только в Directory.Packages.props, а в проектах требуется лишь сослаться на пакет.
Регионы GC – это функция, которая разрабатывается уже несколько лет. Если раньше приходилось иметь несколько больших сегментов памяти (например, 1 ГБ), то теперь GC поддерживает множество маленьких областей (например, 4 МБ). Это позволяет GC быть более гибким в вопросах перепрофилирования областей памяти из одного поколения в другое.
В .NET 7 регионы используются по умолчанию для 64-битных приложений. Подробности по данному вопросу можно получить из статьи архитектора .NET GC.
Rate limiting – это механизм ограничения объёма доступа к ресурсу. Таким образом можно задать определённый лимит доступа, например, к базе данных.
Для написания ограничителя в .NET 7 был добавлен NuGet пакет System.Threading.RateLimiting. В основном работа будет происходить с абстрактным классом RateLimiter. Один из примеров работы от Microsoft:
RateLimiter limiter = GetLimiter();
using RateLimitLease lease = limiter.Acquire(permitCount: 1);
if (lease.IsAcquired)
{
// Do action that is protected by limiter
}
else
{
// Error handling or add retry logic
}
В данном случае мы пытаемся получить 1 разрешение с помощью метода Acquire. Далее идёт проверка – было ли получено разрешение:
Теперь можно быстро и легко создавать контейнерные версии своих приложений, используя команду dotnet publish.
Например:
dotnet add package Microsoft.NET.Build.Containers
dotnet publish --os linux --arch x64 -c Release
-p:PublishProfile=DefaultContainer
В данном случае мы добавляем временную ссылку на пакет для создания контейнера и публикуем проект для linux x64. Результатом выполнения команд является образ, который будет добавлен в Docker. После этого вы можете запустить приложение, используя контейнер:
docker run -it --rm -p 5010:80 my-awesome-container-app:1.0.0
Подробнее про это можно почитать здесь.
Из года в год в .NET растёт производительность. Этот релиз не стал исключением. Только на перечисление всех улучшений нужна отдельная статья, поэтому расскажу только о самых интересных.
Если интересны подробности улучшения производительности в .NET 7, можете почитать о них здесь.
Существенно сокращены накладные расходы на использование рефлексии, когда вызов выполняется несколько раз для одного и того же элемента (будь то метод, конструктор или свойство). Производительность увеличена в 3-4 раза.
Подробнее про улучшение рефлексии можно прочитать здесь.
В .NET 7 повышена производительность LINQ. Например, была существенно улучшена эффективность методов Min и Max при работе с массивами типа int и long. Это достигается за счёт векторизации обработки, а именно – использования Vector<T>. В итоге получаются следующие результаты:
Подробнее про улучшения производительности LINQ можно прочитать в нашей статье.
Кстати, ещё очень здорово, что в System.Linq добавили новые методы Order и OrderDescending. Ранее при использовании OrderBy/OrderByDescending было необходимо ссылаться на собственное значение:
var data = new[] { 2, 1, 3 };
var sorted = data.OrderBy(x => x);
var sortedDesc = data.OrderByDescending(x => x);
Теперь же это не нужно:
var data = new[] { 2, 1, 3 };
var sorted = data.Order();
var sortedDesc = data.OrderDescending();
Сначала я хотел кратко рассказать про улучшения в регулярных выражениях, но в ходе работы над статьёй пришло осознание того, что улучшений слишком много. Поэтому просто оставлю ссылку на большую статью, посвящённую этой теме :). Она в полной мере описывает все нововведения и улучшения регулярных выражений. Здесь же отмечу, что Microsoft не только подняли производительность, но и добавили различные функциональные улучшения.
Как видно, улучшений в .NET 7 довольно много. Не все из них одинаково полезны для всех разработчиков, но многие технологии продолжат своё развитие в рамках будущих выпусков .NET.
Лично для себя могу выделить как наиболее интересные и полезные:
Естественно, в статье были перечислены не все новшества, а только самые интересные (по нашему мнению). Со всеми улучшениями вы можете ознакомиться здесь.
Используете ли вы уже что-то из фишек нового .NET? Пишите в комментариях.
0