Оптимізація продуктивності AR-додатку
AR-додаток на ARKit гріє iPhone 12 до 45°C за 8 хвилин сесії та розряджає батарею на 1% на хвилину. Frame rate — 45–50 FPS замість 60. Це не "трохи тормозить" — це додаток, яким неможливо користуватися. Оптимізація AR — особливо дисципліна: не можна пожертвувати якістю трекінгу задля FPS, не можна убрати освітлення та втратити реалізм, потрібно працювати одночасно з CPU (ARKit/ARCore обробка), GPU (рендеринг) та Neural Engine (якщо є ML-моделі).
Архітектура AR-сесії та де виникають проблеми
ARKit/ARCore працюють безперервно: захоплення кадру з камери → feature detection → оцінка площин → оновлення світової моделі → рендеринг. Кожен етап — обчислювальне навантаження. На iPhone ARKit використовує Neural Engine для трекінгу площин, що сильно розвантажує CPU/GPU. На Android ARCore важче для GPU на пристроях без NPU.
Типові вузькі місця:
Завантаження важких 3D-моделей в ARSCNView без оптимізації: SCNNode з 500K полігонів без LOD, текстури 4096×4096 без mipmapping. GPU рендерить однаково детально об'єкт на передньому плані та у 10 метрах від камери.
Включені фічі трекінгу, які не використовуються. ARWorldTrackingConfiguration з isAutoFocusEnabled = true та environmentTexturing = .automatic без реальної необхідності — постійна навантаження на систему.
Фізика в SCNScene з SCNPhysicsBody на кожному об'єкті при десятках AR-об'єктів — фізичний рушій SceneKit не оптимізований для мобільних AR-сцен з великою кількістю тіл.
Оптимізація ARKit
Конфігурація сесії
let configuration = ARWorldTrackingConfiguration()
// Включаємо тільки те що реально потрібно
configuration.planeDetection = [.horizontal] // не .vertical якщо не потрібно
configuration.isAutoFocusEnabled = false // фіксований фокус — менше навантаження
configuration.environmentTexturing = .none // відключаємо якщо немає PBR-матеріалів
// Для простих сцен — lighter tracking
let simpleConfig = AROrientationTrackingConfiguration() // тільки орієнтація, без world tracking
Для додатків де потрібен тільки face tracking — ARFaceTrackingConfiguration замість ARWorldTrackingConfiguration. Різниця у навантаженню на CPU — відчутна.
Рендеринг через Metal замість SceneKit
ARSCNView зручний, але для складних сцен MTKView + кастомний Metal-рендерер дає повний контроль над draw calls. SceneKit додає overhead на управління нодами та фізику. З ARSession + MTKView:
func session(_ session: ARSession, didUpdate frame: ARFrame) {
let commandBuffer = commandQueue.makeCommandBuffer()!
// Рендеримо captured image (камера)
renderCapturedImage(frame.capturedImage, commandBuffer: commandBuffer)
// Рендеримо AR-контент
renderVirtualContent(frame, commandBuffer: commandBuffer)
commandBuffer.present(drawable)
commandBuffer.commit()
}
Це дає 20–30% приріст FPS на сценах з 10+ AR-об'єктами порівняно з ARSCNView.
Culling та LOD
SCNNode.isHidden = true для об'єктів поза полем зору — SceneKit не рендерит приховані ноди, але виконує physics та update. Правильно — убирати об'єкти з сцени: node.removeFromParentNode().
// Frustum culling вручну
func shouldRenderNode(_ node: SCNNode, camera: ARCamera) -> Bool {
let screenPoint = camera.projectPoint(node.worldPosition,
orientation: .portrait,
viewportSize: viewportSize)
return screenPoint.x > -0.1 && screenPoint.x < 1.1 &&
screenPoint.y > -0.1 && screenPoint.y < 1.1
}
Оптимізація ARCore (Android)
Session config:
val config = Config(session)
config.planeFindingMode = Config.PlaneFindingMode.HORIZONTAL_ONLY
config.lightEstimationMode = Config.LightEstimationMode.DISABLED // +15% батареї
config.depthMode = Config.DepthMode.DISABLED // якщо глибина не потрібна
session.configure(config)
LightEstimationMode.ENVIRONMENTAL_HDR — найдорожчий режим, дає реалістичні відбиття. На пристроях без Depth API (більшість mid-range) використовувати тільки якщо це ключова фіча.
Rendering через Filament (Google's PBR renderer): ARCore-додатки з Filament рендерять PBR-матеріали через Vulkan на підтримуваних пристроях — помітно швидше чим через OpenGL ES. Готовий приклад — arcore-android-sdk samples з Filament-інтеграцією.
Кейс: AR мебельний каталог
Клієнт: додаток для перегляду меблів у AR. Дивани та столи — 3D-моделі від дизайнерів, по 800K–1.2M полігонів кожна. На iPhone 13 — 24 FPS при розміщенні 2 об'єктів. Проблема очевидна.
Робота: експорт моделей через Blender з decimation до 50K полігонів для AR-версії (втрата деталізації невидима з дистанції 1–2 метра на телефоні). Конвертація текстур з PNG 4096×4096 у ASTC 2048×2048. Додавання LOD: висока деталізація для об'єктів ближче 1.5 метра, середня — далі. Результат: 58–60 FPS стабільно, температура нормалізувалась.
Моніторинг продуктивності AR-сесії
// Отримуємо метрики рендерингу
arView.renderOptions.insert(.disableMotionBlur) // убираємо важкі post-effects
// Логуємо frame stats
arView.session.delegate = self
func session(_ session: ARSession, didUpdate frame: ARFrame) {
print("Tracked features: \(frame.rawFeaturePoints?.points.count ?? 0)")
}
На Android: Frame.getTimestamp() різниця між кадрами — якщо > 33ms, пропущений кадр.
Сроки
Аудит продуктивності AR-додатку — 2–3 дні. Оптимізація рендерингу та конфігурації сесії — 1–2 тижні. Якщо потрібна оптимізація 3D-моделей — додатково, залежить від кількості ассетів.







