🗑️ Как Dart убирает мусор в старом поколении: Mark-Sweep vs Mark-Compact
Знаете, почему иногда приложение на Flutter «подвисает» на пару сотен миллисекунд? Чаще всего виноват не ваш код, а сборщик мусора, который устраивает генеральную уборку в старом поколении 🧹 В отличие от молодого поколения, где объекты просто копируются, здесь всё серьезнее: живых объектов много, копировать их дорого, а памяти под «вторую половину» жаба не даст.
Поэтому Dart использует классический двухфазный алгоритм Mark-Sweep:
1️⃣ Mark (Пометка): GC обходит граф от корней (стек, глобальные переменные) и ставит «галочку» в заголовке каждого достижимого объекта.
2️⃣ Sweep (Очистка): Проходит по памяти. Непомеченные → в список свободных блоков (free list). Помеченные → сброс бита. Пустые страницы → возвращаются ОС.
⚠️ Но есть подвох! После Sweep память превращается в «дырявый сыр» 🧀 — фрагментация не позволяет выделить под большой объект кусок памяти, хотя суммарно места хватает.
На помощь приходит Mark-Compact 🚀 При сильной фрагментации живые объекты аккуратно сдвигаются к началу кучи, сливаясь в один монолит. А чтобы не сломать ссылки, используется таблица пересылки (forwarding table) — она быстро вычисляет новый адрес по смещению внутри блока.
💡 Главный вывод для нас, разработчиков: те самые заметные паузы в DevTools — это почти всегда работа со старым поколением. Чем больше у вас долгоживущих объектов (кэши, неочищаемые листы, разросшиеся стейты), тем дольше GC будет «компактировать» кучу.
В следующей части разберем, как движок спасает нас от фризов с помощью Concurrent Marking, барьеров записи и финализаторов. Оставайтесь на связи! 👇
Читать подробный разбор здесь: статья на Хабре
FlutterPulse — канал о мире Flutter!
#flutter #dart #flutterpulse #flutterpulsehabr #garbagecollection #performance #memorymanagement
Post #3058
342