Тестирование потребления оперативной памяти мобильным приложением

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1735 услуг
Тестирование потребления оперативной памяти мобильным приложением
Средний
~2-3 дня
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    495

Тестирование потребления оперативной памяти мобильным приложением

Приложение не крэшится сразу — оно постепенно растёт в памяти. Через 20 минут использования появляется лёгкая задумчивость. Через 40 — системный Memory Pressure убивает фоновые процессы. Через час — SIGKILL от iOS или OOM-киллер Android завершает приложение. Пользователь думает, что приложение «глючит». Firebase Crashlytics ничего не покажет — это не крэш, это убийство системой.

iOS: Instruments Allocations и Leaks

Два шаблона для анализа памяти в Instruments:

Allocations — все выделения памяти, живые и мёртвые объекты. Генерации (кнопка Generation) позволяют сравнить объекты в памяти до и после действия. Если после закрытия экрана объекты этого экрана остались в живой памяти — утечка.

Leaks — автоматический детектор retain-циклов. Красная иконка = найденный цикл. Показывает граф зависимостей с виновниками.

Классический retain-цикл в Swift:

// Утечка: ViewController держит closure, closure захватывает ViewController
class PhotoViewController: UIViewController {
  var onPhotoLoaded: (() -> Void)?

  override func viewDidLoad() {
    super.viewDidLoad()
    onPhotoLoaded = {
      self.imageView.image = UIImage(named: "photo") // strong capture
    }
  }
}

// Правильно:
onPhotoLoaded = { [weak self] in
  self?.imageView.image = UIImage(named: "photo")
}

[weak self] — стандарт для любых closure, захватывающих self в долгоживущих объектах. Instruments Leaks это найдёт, но часто показывает симптом, а не причину. Следуем по графу в стек, ищем корневой strong reference.

UIImage и память

UIImage(named:) кэширует изображение в системном кэше. Для часто используемых иконок — хорошо. Для больших фото, которые загружаются один раз — нет. Используем UIImage(contentsOfFile:) — не кэширует.

Декодирование изображения происходит при первом отображении, не при создании UIImage. Предварительное декодирование на background thread:

func decodedImage(_ image: UIImage) -> UIImage {
  UIGraphicsBeginImageContextWithOptions(image.size, true, 0)
  defer { UIGraphicsEndImageContext() }
  image.draw(in: CGRect(origin: .zero, size: image.size))
  return UIGraphicsGetImageFromCurrentImageContext() ?? image
}

После этого вызова изображение уже декодировано и лежит в памяти как bitmap. Передаём в UI без задержки на декодировку.

Android: Memory Profiler и LeakCanary

Android Studio Memory Profiler показывает Heap в реальном времени: Java Heap, Native Heap, Stack, Code, Graphics. Кнопка Dump Heap сохраняет снимок — анализируем в hprof viewer или конвертируем для Eclipse Memory Analyzer.

Но самый полезный инструмент в бою — LeakCanary. Подключается в debugImplementation, работает автоматически:

// build.gradle.kts
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.14")

При обнаружении утечки LeakCanary показывает notification с полным стеком: что удерживает что, через какую цепочку. Не нужно вручную анализировать heap-dump.

Частые причины утечек на Android:

Context в статических полях или синглтонах:

// Плохо
object ImageCache {
  var context: Context? = null  // держит Activity
}

// Правильно: applicationContext
object ImageCache {
  lateinit var appContext: Context

  fun init(context: Context) {
    appContext = context.applicationContext  // не Activity
  }
}

Незакрытый Cursor от ContentProvider или SQLiteDatabase:

val cursor = db.query(...)
try {
  // работа с курсором
} finally {
  cursor.close()  // обязательно, даже при исключении
}

Listener, не снятый при onDestroy:

override fun onStart() {
  super.onStart()
  locationManager.requestLocationUpdates(provider, 0, 0f, this)
}

override fun onStop() {
  super.onStop()
  locationManager.removeUpdates(this)  // иначе Activity не умрёт
}

Flutter: Observatory и DevTools Memory

Flutter DevTools → Memory tab — snapshot-профилировщик. Показывает группы объектов по типу. Dart:core, package:myapp — смотрим на классы с неожиданно большим количеством экземпляров.

Типичная утечка в Flutter — StreamSubscription без cancel():

class MyWidget extends StatefulWidget { ... }

class _MyWidgetState extends State<MyWidget> {
  late StreamSubscription _sub;

  @override
  void initState() {
    super.initState();
    _sub = someStream.listen((event) { ... });
  }

  @override
  void dispose() {
    _sub.cancel();  // обязательно
    super.dispose();
  }
}

Без _sub.cancel() в dispose() подписка живёт дольше виджета, удерживает замыкание с ссылкой на State.

Что входит в работу

  • Профилирование памяти через Instruments Allocations / Memory Profiler / DevTools
  • Настройка LeakCanary для Android-проекта
  • Анализ heap-dumps и поиск retain-циклов
  • Аудит работы с изображениями (кэш, декодирование)
  • Проверка паттернов работы с listeners, subscriptions, closures
  • Отчёт с конкретными утечками и правками

Сроки

2–3 дня в зависимости от размера приложения и количества найденных проблем. Стоимость рассчитывается индивидуально.