4.2Kпросмотров
74.8%от подписчиков
26 декабря 2025 г.
📷 ФотоScore: 4.6K
Mono vs CoreCLR Последние несколько лет я много писал серверного кода на dotnet, и меня постоянно радовала скорость итерации.
Делаешь изменение — почти моментально получаешь отклик. В Unity это всегда боль. Я постоянно стараюсь работать так, чтобы как можно реже триггерить Domain Reload.
Эта штука на каждое, даже мелкое изменение отнимает десятки секунд.
Если взять обычный день и просто посчитать время на ожидание — легко набегут десятки минут. 🔸Почему так происходит? Редактор Unity на всех платформах работает на Mono — старом кроссплатформенном runtime. В его основе лежит JIT-компиляция. Когда вызывается твой метод первый раз, туда прописан вызов JIT-компилятора. Он берёт IL-код метода, конвертирует в Mono IR (внутреннее представление Mono), оптимизирует, и только после этого генерирует инструкции для конкретного процессора. Казалось бы, при чём тут мы? А при том, что Mono JIT — операция не бесплатная. И в редакторе она обходится очень дорого. 🔸Domain Reload Его порядок работы примерно такой: 1️⃣ Находим все MonoBehaviour и вызываем OnDisable/OnDestroy
2⃣ Выгружаем все .dll движка и наши
3⃣ Освобождаем GC Handles и выгружаем Domain
4⃣ Создаём новый Domain и загружаем все .dll движка
5⃣ Загружаем все .dll игрока
6⃣ Запускаем скрипты с [InitializeOnLoad]
7⃣ На пересозданных MonoBehaviour вызываем Awake/OnEnable На моём проекте Magic Battle Arena (~100к строк кода, 149 сборок) эти 7 пунктов занимают 12 секунд. Угадайте какая операция самая долгая? Mono JIT — примерно 5.5 секунд в сумме. Это происходит потому, что мы вынуждены полностью выгрузить ВСЕ .dll (для которых методы уже скомпилированы) и перекомпилировать их заново. 🔸Почему это нельзя исправить в Mono Проблема фундаментальная. В Mono нет механизма hot swap для сборок. Нельзя сказать "выгрузи только эту dll и загрузи новую версию".
Только полная перезагрузка домена. CoreCLR решает это через AssemblyLoadContext, см. прошлый пост 🔸RyuJIT vs Mono JIT Но даже если Unity не реализует hot reload, сам JIT-компилятор CoreCLR (RyuJIT) работает иначе. Mono JIT — однопроходный. Скомпилировал метод один раз — живи с этим. Хочешь лучше? Используй AOT. RyuJIT поддерживает Tiered Compilation:
🔹Tier 0: быстрая компиляция без оптимизаций (для быстрого старта)
🔹Tier 1: метод был вызван более 30 раз и более? — Оптимизируем его Т.е. при Domain Reload методы сначала компилируются максимально быстро, а потом в фоне докомпилируются с оптимизациями.
Время ожидания сокращается, performance не страдает. Но выиграем мы от смены JIT компилятора, я уверен не так много, как c перехода с Domain Reload на Code Reload. 🔻Мой прогноз:
Время Domain Reload снизится минимум на 75%. В моём примере — с 12 секунд до 3. Останутся только вызовы Awake/Destroy и десериализация состояния сцен. Проверим в 2025 2026 или 2027 году 🤣 Теперь ты знаешь что загадать на Новый Год 😊 Ставь 👍 если тебе заходит такого рода контент!
Ты знаешь кому переслать эту статью 💪 #unite2025@UniArchitect
#проект_в_разработке@UniArchitect