Программирование и разработка программного обеспечения

Улучшения .NET 11: накопительный прирост производительности — от JIT до асинхронного программирования

Microsoft представляет сотни улучшений в .NET 11, уделяя особое внимание JIT-компилятору, сокращению аллокаций, оптимизации вызовов интерфейсов и делегатов, а также внутренней структуре async/await. Опубликованные результаты показывают, что прирост достигается за счёт удаления ненужных проверок, аллокаций и вызовов, а не благодаря одному крупному изменению.

2026-09-15
5 мин. чтения
5 просмотров
فريق تحرير certi.news
Улучшения .NET 11: накопительный прирост производительности — от JIT до асинхронного программирования

В записи, опубликованной Microsoft в .NET Blog 15 сентября 2026 года, рассматриваются сотни улучшений, вошедших в .NET 11. Они представлены как совокупный результат продолжительной работы над JIT-компилятором, средой выполнения и библиотеками. Основная идея заключается не в наличии одной функции, удваивающей производительность, а в устранении множества небольших повторяющихся издержек: проверки границ, которая больше не нужна, отменённой аллокации памяти, предотвращённой блокировки или системного вызова, а также циклов, выполняющихся за меньшее число тактов процессора.

Важность таких улучшений состоит в том, что значительная их часть не требует изменения или переработки кода приложений. JIT-компилятор преобразует промежуточный язык IL, обычно создаваемый из C#, F# и Visual Basic, в машинные инструкции, выполняемые процессором. Если ему удаётся доказать, что виртуальный вызов можно направить к определённому типу или что конкретная проверка не завершится ошибкой, он может сгенерировать более короткие инструкции и повысить вероятность встраивания функций друг в друга.

Устранение абстракций

Заметная часть материала посвящена тому, что Microsoft называет устранением абстракций, то есть возможности среды выполнения обходить исполнительные издержки некоторых абстракций, необходимых разработчику при проектировании программы. Например, при вызовах интерфейсов и виртуальных методов традиционное выполнение может потребовать загрузки нескольких указателей и косвенного вызова, что препятствует встраиванию вызываемой функции в текущую.

.NET 11 продолжает развивать подход «защищённой деvirtualизации» (Guarded Devirtualization). JIT распознаёт наиболее распространённый тип во время выполнения, создаёт быстрый путь для прямого вызова и сохраняет виртуальный путь, чтобы обеспечить корректность выполнения, если позднее появится другой тип. Когда это позволяет встроить функцию, становятся возможны и другие оптимизации, такие как распространение констант, удаление ветвлений и проверок границ.

Работа распространяется на обобщённые виртуальные методы, операции ReadyToRun и NativeAOT, а также виртуальные реализации по умолчанию в интерфейсах. В материале отмечается, что эти улучшения могут увеличить размер кода, если прямые вызовы приводят к большему числу встраиваний, но при этом делают логику программы более доступной для оптимизатора.

Меньше аллокаций и меньшая нагрузка на сборщик мусора

.NET 11 также продолжает развивать анализ escape analysis, который пытается определить, выходит ли объект, созданный внутри функции, за пределы этой функции. Если доказано, что он не покидает эту область, JIT может не размещать его в управляемой куче или в некоторых случаях полностью устранить аллокацию, снижая нагрузку на сборщик мусора.

Источник приводит примеры улучшения упаковки nullable-значений (Nullable boxing) и условного анализа выхода за пределы области видимости при перечислении коллекций. В одном из измерений аллокация размером 32 байта исчезла при перечислении коллекции, построенной на поле экземпляра, а время выполнения снизилось с 13,874 наносекунды в .NET 10 до 2,674 наносекунды в .NET 11. Некоторые сценарии с обобщёнными значениями или вызовами интерфейсов также получили возможность избегать временных аллокаций размером 24 байта.

Эти показатели относятся к очень малым операциям, поэтому их не следует воспринимать как неизменный общий прирост производительности каждого приложения. Их основная ценность заключается в демонстрации шаблонов кода, которые среда выполнения может оптимизировать, тогда как фактический эффект будет зависеть от характера приложения и его горячих путей.

Делегаты и асинхронная среда выполнения

.NET 11 включает изменения в представлении делегатов в CoreCLR, в том числе удаление поля размером с один указатель из каждого объекта делегата в 64-битном процессе, что, согласно материалу, даёт экономию 8 байт на каждый делегат. Также были переставлены поля в представлении делегатов в NativeAOT, а некоторые используемые вместе значения размещены в памяти рядом для улучшения доступа к ним на таких архитектурах, как Arm64.

В записи также представлена новая архитектура под названием «runtime async», которая переносит часть ответственности за преобразование методов async/await с компилятора C# на JIT и среду выполнения. В традиционной модели компилятор создаёт конечный автомат с полями, необходимыми для возобновления работы, например параметрами, локальными значениями, объектами ожидания и состоянием выполнения. Новая модель использует меньший контракт в IL, а затем оставляет среде выполнения и JIT решения, связанные с тем, что остаётся живым в точках приостановки, как размещать объекты продолжения и как создавать внешне видимые Task или ValueTask.

Что меняется на практике?

Редакционный вывод из этого раунда заключается в том, что .NET 11 в большей степени делает ставку на оптимизацию существующего кода, чем на добавление новых API. Приложения, активно использующие интерфейсы, обобщённые методы, делегаты, перечисление и асинхронные операции, могут получить преимущества без непосредственных изменений исходного кода, однако масштаб улучшений будет различаться в зависимости от процессора, операционной системы, настроек среды выполнения и характера нагрузки.

Microsoft рекомендует проверять результаты с помощью BenchmarkDotNet, установив .NET 10 и .NET 11 и запустив один и тот же код в обеих версиях. Компания предупреждает, что опубликованные измерения представляют собой очень точные тесты и могут зависеть от оборудования, других процессов и настроек среды. Поэтому результатов небольшого теста недостаточно для принятия решения об обновлении или доказательства общего улучшения; перед более широкими выводами необходимо измерить реальные нагрузки приложения.

Источник новости
ف
Автор

فريق تحرير certi.news

В той же категории

Вам также может понравиться

Все новости