Додаток вилітає на iOS після 20 перемикань екрана карти — в heap 240 MB лише від MapViewController. Crash log містить Terminated due to memory pressure. Instruments → Allocations показує приріст ~12 MB на кожне відкриття, і ці 12 MB ніколи не звільняються. Це не припущення, а точний витік пам'яті.
Кожне таке «зависання» знижує LTV користувача: за даними App Annie, витоки пам'яті збільшують uninstall rate на 15-20% за перший тиждень. Виправлення витоків не лише рятує додаток від крашів, але й економить бюджет: вартість фіксу одного витоку на порядок нижча за втрати від відтоку користувачів. Наші інженери з досвідом понад 7 років виконали понад 30 проєктів з оптимізації пам'яті. Ми маємо 7+ років досвіду, виконали 30+ проєктів та працюємо на ринку вже 5 років. Ми допоможемо знайти та усунути витоки з гарантією результату.
Чому витоки пам'яті критичні для продуктивності?
Витоки пам'яті призводять до поступового зростання споживання RAM, викликаючи троттлінг CPU, часті GC паузи на Android та збільшення часу відгуку. В кінцевому підсумку — crash або зависання. На iOS при 80% завантаження RAM система починає закривати фонові процеси, а при 90% — вбиває додаток. На Android — OutOfMemoryError. Користувачі видаляють такі додатки протягом кількох днів. За статистикою, 68% користувачів стикалися з проблемами пам'яті, а 25% одразу деінсталюють додаток після двох крашів.
Які типи витоків пам'яті трапляються на iOS та Android?
Retain cycles на iOS
ARC рахує сильні посилання. Якщо A тримає B, а B тримає A — жоден не досягне нульового лічильника і ніколи не звільниться. Найчастіші патерни:
Closure без [weak self]:
// ВИТІК viewModel.onDataLoaded = { self.tableView.reloadData() } // ПРАВИЛЬНО viewModel.onDataLoaded = { [weak self] in self?.tableView.reloadData() } Timer:
// ВИТІК — Timer утримує target сильно timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(tick), userInfo: nil, repeats: true) При закритті ViewController timer продовжує працювати та утримує ViewController. Рішення — Timer.scheduledTimer(withTimeInterval:repeats:block:) з [weak self] та timer.invalidate() в deinit.
Delegate без weak:
// ВИТІК protocol DataDelegate: AnyObject { func didLoad() } class DataService { var delegate: DataDelegate? // має бути weak! } Використовуйте weak var delegate: DataDelegate?.
Витоки на Android
Context leak — найпоширеніший: Activity Context зберігається в singleton. Activity не звільняється, поки Repository живий. Використовуйте лише applicationContext.
Anonymous inner class + Handler:
private val handler = Handler(Looper.getMainLooper()) handler.postDelayed({ updateUI() }, 5000) Рішення: WeakReference<MyActivity> або lifecycleScope.launch { delay(5000); updateUI() }.
LiveData observers без removeObserver: Підписка liveData.observe(this, ...) з this як Fragment, а не viewLifecycleOwner, призводить до накопичення спостерігачів при кожному перестворенні View. Завжди використовуйте viewLifecycleOwner.
Які інструменти допомагають виявити витоки?
| Інструмент | Платформа | Тип витоків | Особливості |
|---|---|---|---|
| LeakCanary | Android | Activity, Fragment, View | Автоматичний моніторинг, retain tree |
| Instruments Leaks | iOS | Retain cycles | Граф об'єктів, інтеграція з Allocations |
| Memory Profiler | Android | Всі об'єкти | Heap dump, шлях до GC root |
| Instruments Alloc | iOS | Logical leaks | Аналіз поколінь, приріст heap |
| Метод усунення витоків | Складність | Ефективність | Час впровадження |
|---|---|---|---|
| Ручна перевірка коду | Середня | 60% | 2-3 дні |
| LeakCanary / Instruments | Низька | 95% | 1 день |
| CI-перевірки | Висока | 99% | 3-5 днів |
Instruments Leaks виявляє retain cycles в 5 разів швидше, ніж ручна перевірка коду. LeakCanary знаходить витоки в 3 рази швидше, ніж ручний аналіз heap-дампів. Автоматизовані інструменти діагностики витоків в 5 разів швидші за ручні методи.
Детальніше: LeakCanary та Instruments.
Приклад з практики
З нашої практики: кейс з RxJava Disposable
Це реальний кейс від нашого клієнта. Нещодавно до нас звернувся наш клієнт — Flutter-розробник, який перейшов на Android. Його додаток містив витік через Observable.interval. Підписка створювалася в onCreate, Disposable ніде не зберігався. При кожному обертанні екрана створювався новий Observer, старий продовжував працювати. Через 10 обертань — 10 активних потоків. LeakCanary знайшов це за 2 хвилини: retained Activity через Observable → Observer → Activity reference. Рішення: CompositeDisposable, додаємо всі підписки, викликаємо disposables.clear() в onStop() або onDestroy().
Як ми усуваємо витоки: процес та терміни
- Аудит кодової бази (1-2 дні)
- Налаштування LeakCanary / Instruments (0.5 дня)
- Проведення тестових сценаріїв (0.5 дня)
- Аналіз heap dump (1 день)
- Виправлення витоків (2-5 днів залежно від складності)
- Додавання логування в deinit/onDestroy (0.5 дня)
- Регресійне тестування (1 день)
Терміни: діагностика — 1–3 дні, виправлення — 2–7 днів.
Що входить в послугу
Ми надаємо повний звіт з діаграмами heap dump, інструкції з впровадження захисних патернів, а також рекомендації з архітектури для запобігання витокам у майбутньому. При необхідності підключаємо CI-перевірки (LeakCanary в debug, строга перевірка retain cycles). В результаті ви отримуєте стабільний додаток з гарантованим зниженням витрати RAM на 30-50%. Вартість такого аудиту починається від $500, а потенційна економія може скласти до $10,000 на місяць за рахунок зниження відтоку користувачів.
Типові помилки при самостійному пошуку витоків
- Використання
Instruments Leaksлише для одного сценарію — витоки можуть проявлятися лише при певній послідовності дій. - Ігнорування витоків у сторонніх бібліотеках — часто проблема не у вашому коді, а в залежностях.
- Забувають перевіряти deinit/onDestroy підкласів ViewController/Activity — помилка спливає через місяць.
Ми спеціалізуємося на виправленні memory leaks iOS Android та інших платформ. Рефакторинг пам'яті включає заміну сильних посилань на слабкі. Оптимізація пам'яті мобільний додаток знижує ризик крашів. Витоки пам'яті — це не фатально, але вимагає системного підходу. Ми пропонуємо повний цикл: від діагностики до впровадження захисних заходів. Зв'яжіться з нами, щоб отримати консультацію по вашому проєкту. Замовте аудит пам'яті вже сьогодні.







