← Назад к вопросам

Как работает память и garbage collection в Dart?

3.0 Senior🔥 62 комментариев
#Dart

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Память и Garbage Collection в Dart

Модель памяти

Dart использует поколенческую сборку мусора (generational GC), разделяя объекты на два поколения:

  • Young Space — для короткоживущих объектов
  • Old Space — для долгоживущих объектов

Young Space и Scavenger

Young Space делится на два полупространства: active и inactive. Алгоритм semi-space copying:

  1. Новые объекты создаются в active space
  2. Когда active space заполнен — запускается Minor GC
  3. Живые объекты копируются в inactive space
  4. active и inactive меняются местами
  5. Объекты, пережившие несколько циклов, перемещаются в Old Space

Этот процесс занимает менее 1 мс, что критично для Flutter (60/120 FPS).

Old Space и Mark-Sweep-Compact

Для старого поколения используется mark-sweep-compact:

  1. Mark — обходит граф объектов от корней, помечая живые
  2. Sweep — удаляет непомеченные объекты
  3. Compact — дефрагментирует память
class LongLivedCache {
  final Map<String, dynamic> _data = {};
  
  void put(String key, dynamic value) {
    _data[key] = value;  // _data живёт долго -> Old Space
  }
}

Изоляты и память

Каждый Isolate в Dart имеет собственную кучу и собственный GC:

await Isolate.spawn((message) {
  // Собственный heap, собственный GC
  final list = List.generate(1000000, (i) => i);
  // GC этого Isolate не блокирует UI
}, 'start');

Это означает:

  • Нет shared memory между Isolate (безопасность)
  • GC одного Isolate не блокирует другие
  • UI Isolate остаётся отзывчивым

Оптимизация для Flutter

Избегайте аллокаций в build()

// Плохо — новый список каждый build()
Widget build(BuildContext context) {
  final items = data.map((e) => Text(e)).toList();
  return Column(children: items);
}

// Хорошо — кэшируйте
final _cachedWidgets = data.map((e) => Text(e)).toList();

Используйте const конструкторы

const EdgeInsets.all(16.0)  // Один объект при компиляции
EdgeInsets.all(16.0)        // Новый объект каждый раз

Управляйте подписками

class MyState extends State<MyWidget> {
  StreamSubscription? _sub;
  
  void initState() {
    _sub = stream.listen((data) => setState(() {}));
    super.initState();
  }
  
  void dispose() {
    _sub?.cancel();  // Обязательно! Иначе утечка
    super.dispose();
  }
}

Сравнение

ПараметрYoung GCOld GC
АлгоритмSemi-space copyingMark-Sweep-Compact
Скорость< 1 мс5-50 мс
ЧастотаЧастоРедко
ОбъектыКороткоживущиеДолгоживущие

Мониторинг

Dart DevTools предоставляет Memory profiler: heap snapshot, allocation tracking, GC timeline.

Dart GC оптимизирован для UI-приложений: минимальные паузы, поколенческий подход, изоляция через Isolate.