Start Debugging

jit

7 статей

Цикл по ref T против индексации Span<T> в C#: почему версия со span не медленнее, а часто быстрее в .NET 10

В .NET 10 обычный цикл for по span[i] с границей span.Length компилируется в цикл без проверки границ, со снижением стоимости операций (strength reduction) и обратным отсчётом. Написанный вручную цикл с Unsafe.Add(ref r, i) и индексом int сохраняет расширение знака и сравнение при счёте вверх и в замерах оказался на 2-5% медленнее. Бенчмарки и дизассемблер JIT для arm64 и x64 на .NET 10.0.10.

Что такое transparent-раскладка структуры и почему структура-обёртка с одним полем меняет соглашение о вызовах в .NET?

Transparent-структура - это структура, которую ABI обрабатывает точно так же, как её единственное поле. В .NET 11 такой гарантии нет: структура, оборачивающая double, передаётся в RCX в Windows x64, но в XMM0 в Linux и macOS. Здесь разобран дизассемблированный код JIT-компилятора .NET 11 для трёх ABI, ошибки P/Invoke, которые из этого возникают, и способы писать типы-обёртки, безопасные на любой границе.
2026-09-16 dotnetdotnet-11jit

JIT в .NET 11 девиртуализирует обобщённые виртуальные методы, и вместе с ними исчезает выделение памяти

В статье Стивена Тоуба Performance Improvements in .NET 11 вызовы обобщённых виртуальных методов падают с 6.7 нс и 24 байт до 1.8 нс и нуля выделений. Три пул-реквеста в RyuJIT открыли инлайнинг для самой непрозрачной диспетчеризации в .NET.
2026-09-04 dotnetnative-aotjit

Что такое флаг W^X в .NET и нужен ли он Native AOT?

W^X (write xor execute) - правило, по которому ни одна страница памяти не бывает одновременно записываемой и исполняемой. В .NET это переключатель DOTNET_EnableWriteXorExecute, включённый по умолчанию с .NET 7, и существует он исключительно ради JIT. Native AOT его никогда не читает. Разбираем, как среда выполнения его реализует, во что он обходится и когда его отключение - законное решение.

Что такое PGO в .NET и нужно ли его включать?

PGO (оптимизация на основе профиля) позволяет JIT-компилятору .NET специализировать горячий код под типы и ветви, которые действительно встречаются в вашей нагрузке. Dynamic PGO включён по умолчанию начиная с .NET 8, поэтому в .NET 8 и более поздних версиях включать его не нужно. Вот что он делает, как увидеть его эффект и те редкие случаи, когда стоит тронуть настройку.

Что такое многоуровневая компиляция и как о ней рассуждать?

Многоуровневая компиляция позволяет JIT в .NET компилировать каждый метод дважды: сначала быстро и без оптимизаций, чтобы приложение запустилось, а затем ещё раз с полными оптимизациями, когда среда выполнения узнаёт, что метод горячий. Здесь показано, как tier 0, tier 1, замена на стеке и Dynamic PGO складываются вместе, и как их наблюдать и настраивать.