M
Minutri | Unity
@minutri651 подп.
1.4Kпросмотров
22 мая 2024 г.
questionScore: 1.5K
👀🗑Сборка мусора в Unity? Путь&nbsp;GC.Collect(). Давайте проследим некоторый путь. Путь GC.Collect(). Но сначала. Что такое GC.Collect()? Это принудительный вызов сборки мусора. Во что превращается GC.Collect? Ведь мы знаем, что Unity использует другой сборщик, который называется Boehm GC,&nbsp;а следовательно GC.Collect должен во что-то транслироваться. Чтобы ответить на этот вопрос, нужно проследить путь преобразования кода. 1️⃣&nbsp;Давайте напишем простой класс (Убираю лишние переносы в целях экономии места в посте; Длинные имена, сокращены для простоты чтения&nbsp;): public class Minutri : MonoBehaviour { private void Start() { GC.Collect(); GC.Collect(2, GCCollectionMode.Forced); } } Два разных вызова — чтобы посмотреть, куда уходит двойка, а куда GCCollectionMode.Forced. GC.Collect(2, GCCollectionMode.Forced) говорит о том, что нужно вызвать сборку вплоть до второго поколения с forced. Но не забываем — мы работаем с Boehm GC. Поэтому про работу с поколениями не может идти речи. Как же получается? Написать так можно — а поколений нет. Смотрите далее) 2️⃣&nbsp;После трансляции IL2CPP находим метод Start класса Minutri. Называется он у меня Minutri_Start_... 3️⃣&nbsp;В Assembly-CSharp.cpp наблюдаю, во что превратился метод: void Minutri_Start_ (Minutri_t* __this, ) { static bool s_Il2CppMethodInitialized; // <------ а GC_Collect_m(NULL); // <------ б GC_Collect_m(2, 1, NULL); return; Интересовать нас может сразу два пункта: а) Видим использование static bool. Напоминаю — это медленно. б) Оба метода GC_Collect&nbsp;раскрылись, мы их наблюдаем, и они похожи. 4️⃣&nbsp;Идем глубже, в методы&nbsp;GC_Collect_m... void GC_Collect_m() { static bool s_Il2CppMethodInitialized; L_0 = GC_get_MaxGeneration_m(NULL); GC_InternalCollect_m(L_0, NULL); } а) Опять static bool. б) Воу 🤨&nbsp;Все-таки получаем максимальное поколение. Получается, я вам врал! Какой ужас. (нет) в) Вызываем GC_InternalCollect_m&nbsp;и передаем туда "максимальное поколение". Давайте я вам помогу, и мы не будем заходить в GC_get_MaxGeneration_m. Он возвращает ноль. Но это и неважно. Сейчас все увидите. 5️⃣&nbsp;Зайдем глубже, в GC_InternalCollect_m. Мы видим метод. Там опять нам всё не нужно, кроме одной строки: (()mscorlib::System::GC::InternalCollect) (___0_generation); Заходим в InternalCollect. Далее в Collect(generation) 6️⃣&nbsp;Ну что ж. Мы пришли, поздравляю!) Метод Collect&nbsp;перед вами целиком: void il2cpp::gc::GarbageCollector::Collect(int maxGeneration) { #if IL2CPP_ENABLE_DEFERRED_GC if (GC_is_disabled()) s_PendingGC = true; #endif GC_gcollect(); } Тут, как мы видим, всё: последнее упоминание поколений. Глубже мы не пойдем. Вы видите, чтобы maxGeneration&nbsp;параметр где-то использовался? Вот и я не вижу. Зачем они так сделали? Вероятней всего для того, чтобы в случае использования другого GC можно было быстро перейти на поколения. Так, а что у нас с GC.Collect(2, GCCollectionMode.Forced)? Там пойдут goto и прочие вещи, которые здесь не буду рассматривать, так как не хватит места в посте. Но, короче говоря: в нем будет вызов этого же Collect из пункта 6️⃣. То есть, что бы мы ни указывали в аргументы GC.Collect&nbsp;— это не имеет значения. Резюмируем: — GC в .NET C# поколенческий, в Unity - нет — Вызов сборки мусора конкретного поколения вызывает сборку мусора в целом — Перегрузки GC.Collect, при настройке билда в IL2CPP не влияют на перформанс и ничего не ломают #thematic_post #gc
1.4K
просмотров
3480
символов
Да
эмодзи
Нет
медиа

Другие посты @minutri

Все посты канала →
👀🗑Сборка мусора в Unity? Путь&nbsp;GC.Collect(). Давайте п — @minutri | PostSniper