Мониторинг производительности мобильного приложения в продакшене
Xcode Instruments в CI не запустишь, и пользователь не пришлёт профиль аллокаций. Мониторинг производительности в продакшне — это отдельная задача с инструментами, которые работают на устройстве, не мешают пользователю и отправляют агрегированные метрики на сервер.
Что измеряем и какими инструментами
Firebase Performance Monitoring — нулевой порог входа. SDK автоматически измеряет: время cold start, HTTP-запросы (latency, payload size, success rate), время рендеринга экранов. Добавляем кастомные трейсы для любого кода:
// iOS — кастомный трейс для критичной операции
let trace = Performance.startTrace(name: "catalog_load")
trace.start()
catalogService.load { [weak self] result in
trace.stop() // метрика уходит в Firebase
self?.handleResult(result)
}
// Android
val trace = Firebase.performance.newTrace("catalog_load")
trace.start()
catalogRepository.load { result ->
trace.stop()
handleResult(result)
}
Sentry Performance — если Sentry уже используется для крэшей, Performance Monitoring включается без доп. SDK. Даёт distributed tracing: видно не только время операции на клиенте, но и разбивку по API-запросам, которые она порождает.
Datadog RUM — для команд с существующей Datadog-инфраструктурой. Автоматически трекает Session Replay (запись взаимодействий пользователя), Frame Rate, Network requests с full stack trace.
Метрики, которые реально влияют на retention
FPS в скролле — один из ключевых показателей perceived performance. UITableView дёргается при быстром скролле из-за синхронной декодировки JPEG на main thread — это классическая проблема. Измеряем через CADisplayLink и отправляем p5 (процент кадров ниже 60fps) в аналитику:
// Простой FPS-монитор
class FPSMonitor {
private var displayLink: CADisplayLink?
private var lastTimestamp: CFTimeInterval = 0
private var frameCount = 0
func start() {
displayLink = CADisplayLink(target: self, selector: #selector(tick))
displayLink?.add(to: .main, forMode: .common)
}
@objc private func tick(_ link: CADisplayLink) {
frameCount += 1
if link.timestamp - lastTimestamp >= 1.0 {
let fps = Double(frameCount) / (link.timestamp - lastTimestamp)
MetricsCollector.record("screen_fps", value: fps, screen: currentScreen)
frameCount = 0
lastTimestamp = link.timestamp
}
}
}
На Android — FrameMetricsAggregator из androidx.core даёт детальную разбивку по фазам рендеринга.
Memory warnings — iOS отправляет didReceiveMemoryWarning перед тем как убить приложение. Логируем это событие с текущим экраном и объёмом allocated memory через task_info:
NotificationCenter.default.addObserver(
forName: UIApplication.didReceiveMemoryWarningNotification,
object: nil, queue: .main
) { _ in
Analytics.logEvent("memory_warning", parameters: [
"current_screen": AppRouter.currentScreen,
"memory_mb": memoryUsageMB()
])
}
Алерты и пороги
Настраиваем алерты в Firebase Performance или Datadog на:
- Cold start time > 3s (p75) — Apple рекомендует < 400ms до первого кадра
- HTTP error rate > 2%
- Screen render time > 500ms (p95)
- ANR rate (Android) > 0.1%
- App not responding (iOS watchdog kills) — через crash rate Crashlytics
Главное: не ставить алерты на слишком низкие пороги — alert fatigue убивает реакцию на реальные проблемы.
Что входит в работу
- Интеграция Firebase Performance / Sentry Performance / Datadog RUM
- Кастомные трейсы на ключевые операции (загрузка, навигация, бизнес-процессы)
- FPS-мониторинг и memory monitoring
- Настройка алертов с нотификациями в Slack/Telegram
- Dashboard с ключевыми метриками производительности
Сроки
Интеграция SDK + кастомные трейсы + алерты: 1–3 дня. Стоимость рассчитывается индивидуально.







