A lassú alkalmazás a fő ok, amiért a felhasználók törlik a programokat. A milliszekundumos késés induláskor vagy lista görgetésekor tíz százalékkal csökkenti a megtartást. A teljesítmény (performance) nem csak sebesség, hanem stabilitás is: ANR, összeomlások és memóriaszivárgások hiánya. Ez a cikk a teljesítmény minden aspektusát lefedi: a memóriakezeléstől (GC, ARC) az eszközökkel való profilozásig. Bővebben a hivatalos Android Performance útmutatóban.
Főbb pontok
Az alkalmazás teljesítménye közvetlenül kapcsolódik a jank-hoz — észlelhető késés a felhasználói művelet és a UI válasza között. Fő okok: a főszál blokkolása (nehéz műveletek a UI szálon), gyakori elrendezés-újrarajzolás (overdraw), memóriaszivárgások (gyakori GC), nem optimális algoritmusok (O(n²) nagy adathalmazokon). Frame Rate (FPS) — képkockák száma másodpercenként. A kényelmes élményhez stabil 60 FPS (Android) vagy 120 FPS (iPhone Pro, iPad Pro) szükséges. A VSync szinkronizálja a megjelenítést a képernyő frissítési gyakoriságával.
A jank akkor jelentkezik, ha egyetlen képkocka megjelenítése meghaladja a 16,6 ms-ot (60 FPS esetén) vagy a 8,3 ms-ot (120 FPS esetén). A GPU-profilozás (Profile GPU Rendering Androidon, Core Animation iOS-en) megmutatja, mely megjelenítési fázisok vesznek igénybe a legtöbb időt. Fő fázisok: Layout (elemek elhelyezése), Draw (rajzolás), Display (átvitel a képkocka pufferbe). A leggyakoribb probléma az elrendezés inflációja XML-ben, különösen összetett, egymásba ágyazott ConstraintLayout használatakor.
Time-to-Interactive (TTI) — az idő, amíg az alkalmazás teljesen készen áll az interakcióra. A TTI magában foglalja a Cold Start-ot, az adatok betöltését és a könyvtárak inicializálását. A Google a TTI-t 5 másodperc alatt, az Apple — 2 másodperc alatt javasolja a fő képernyők esetében. Lusta betöltés — a tartalom és könyvtárak késleltetett betöltésének technikája, kritikus a TTI javításához. Az IT Sectr-nél alapértelmezetten lusta inicializálást használunk minden projektben.
Az ANR és az összeomlás a mobilalkalmazás-teljesítmény fő ellenségei. ANR (Application Not Responding) — párbeszédpanel Androidon, amely akkor jelenik meg, ha a főszál több mint 5 másodpercig blokkolva van. Okok: szinkron hálózati kérések a UI szálon, adatbázis-munka korutin nélkül, nagy bitmap dekódolás downsampling nélkül, deadlock a főszálon. Az ANR hívási verem a /data/anr/traces.txt fájlba kerül mentésre, és lehetővé teszi a pontos blokkolási hely meghatározását.
Összeomlás — az alkalmazás váratlan befejeződése. Androidon — Exception (Java/Kotlin) vagy Signal (natív kód). iOS-en — NSException vagy jel (EXC_BAD_ACCESS — hozzáférés felszabadított memóriához). Összeomlás-jelentő eszközök: Firebase Crashlytics, Sentry, BugSnag. Ezek stacktrace-t, eszközadatokat és reprodukciós lépéseket gyűjtenek. Stack Overflow — a hívási verem túlcsordulása végtelen rekurzió miatt. OutOfMemoryError — amikor a verem megtelik.
StrictMode — Android eszköz a szálbiztonsági megsértések észlelésére. Lehetővé teszi szabályok beállítását: ThreadPolicy (lemez/hálózat tiltása a főszálon), VmPolicy (Activity, SQLite, CloseGuard szivárgások észlelése). A StrictMode-ot csak debug buildben szabad bekapcsolni — release-ben nem működhet. iOS-en a megfelelője a Main Thread Checker (Xcode), amely automatikusan észleli a nem a főszálon történő UIKit-hívásokat.
Memóriaszivárgás (Memory Leak) — az a helyzet, amikor egy objektum a memóriában marad, bár az alkalmazás már nem használja. Ez közvetlenül csökkenti az alkalmazás teljesítményét. Androidon a GC (Garbage Collection) nem tud begyűjteni egy objektumot, ha erős hivatkozás van rá. Tipikus okok: statikus hivatkozások Activity-re, nem törölt callback-ek/megfigyelők, belső osztályok implicit hivatkozással a külső osztályra, Handler nem törölt üzenetekkel. LeakCanary — könyvtár az automatikus szivárgásészleléshez.
ARC (Automatic Reference Counting) — memóriakezelési modell iOS-en. Minden objektumnak van referenciaszámlálója (retain count). Amikor a számláló nullát ér el, a memória felszabadul. Retain Cycle akkor következik be, amikor két objektum erős hivatkozást tart egymásra (A → B és B → A). Az ARC soha nem nullázza a számlálókat. Megoldás: gyenge (weak) vagy gazdátlan (unowned) hivatkozások. A weak automatikusan nil lesz az objektum felszabadulásakor. Az unowned nem lesz nil, de garantálja, hogy az objektum él.
GC (Garbage Collection) Androidon (Java/Kotlin) működik. A GC időszakosan felfüggeszti a végrehajtást (Stop-the-World szünet), hogy megtalálja és felszabadítsa az elérhetetlen objektumokat. GC trigger: amikor a verem egy bizonyos százalékig megtelik. Az ARC iOS-en (Swift/Objective-C) működik, és nincsenek szünetei — a számlálók atomikusan frissülnek minden hozzárendeléskor. Az ARC kiszámíthatóbb, de magas hozzárendelési gyakoriság mellett túlzott retain/release műveleteket halmozhat fel.
Gyenge hivatkozás (Weak Reference) és erős hivatkozás (Strong Reference) — a hivatkozás típusa határozza meg, hogy a GC/ARC felszabadíthatja-e az objektumot. Strong Reference — az objektum nem kerül begyűjtésre, amíg ez a hivatkozás létezik. Weak Reference — a GC/ARC begyűjtheti az objektumot; a gyenge hivatkozás nil lesz (Swift/Java WeakReference-ben). Unowned Reference (Swift) — nem lesz nil a felszabadításkor; hozzáférés az objektum halála után összeomlást okoz. Androidon a java.lang.ref.WeakReference használatos gyenge hivatkozásokhoz.
Példa szivárgás észlelésére Androidon a LeakCanary segítségével:
// Утечка: анонимный класс держит ссылку на Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
// Используем `this@MainActivity`, сохраняя ссылку на Activity
Log.d("TAG", "Handler received message")
}
}
handler.sendEmptyMessageDelayed(0, 60000)
}
}
// Исправление: статический Handler + WeakReference
class SafeHandler(activity: MainActivity) : Handler() {
private val weakActivity =
WeakReference(activity)
override fun handleMessage(msg: Message) {
weakActivity.get() ?: return
Log.d("TAG", "Handler received message")
}
}
A profilozás az alkalmazás teljesítményének mérési folyamata: CPU, memória, hálózat, energiafogyasztás. Profilozás nélkül a vak optimalizálás haszontalan — nem fogja tudni, hogy a kód melyik része lassú valójában.
| Eszköz | Platform | Mér | Mikor használja |
|---|---|---|---|
| Instruments (Time Profiler) | iOS | CPU, függvényhívások, végrehajtási idő | Algoritmus optimalizálás, szűk keresztmetszetek keresése |
| Instruments (Allocations) | iOS | Memória, objektumok száma, retain counts | Szivárgások és túlzott memóriahasználat keresése |
| Instruments (Leaks) | iOS | Retain cycles, memóriaszivárgások | Rendszeres ellenőrzés kiadás előtt |
| Android Profiler (CPU) | Android | CPU-használat, szál aktivitás, traces | A főszál blokkolásainak keresése |
| Android Profiler (Memory) | Android | Heap dump, foglalás követés | Szivárgások keresése, objektum elemzés |
| Android Profiler (Network) | Android | Forgalom, sebesség, kérések időzítése | Hálózati hívások optimalizálása |
| LeakCanary | Android | Automatikus memóriaszivárgás észlelés | A fejlesztés minden szakaszában |
| StrictMode | Android | Lemez/hálózat a főszálon, szivárgások | Debug build |
| Traceview / Systrace | Android | Módszer követés, rendszer események | Mély szintű késleltetés elemzés |
Instruments (Xcode) — a legerősebb eszköz iOS-hez. A Time Profiler megmutatja, mely függvények fogyasztják a legtöbb CPU-t. Az Allocations követi az objektumok létrehozását és felszabadítását. A Leaks automatikusan megtalálja a retain cycle-okat. A profilozás lépései: (1) indítsa el az Instruments-t; (2) válasszon sablont (Time Profiler CPU-hoz); (3) futtassa a problémás forgatókönyvet; (4) elemezze a hívási vermet — a legszélesebb oszlop a "legforróbb" függvény.
Az Android Profiler be van építve az Android Studio-ba (View → Tool Windows → Profiler). A CPU Profiler mutatja az egyes szálak terhelését. Memory Profiler — heap dump és foglalás követés. Network Profiler — az összes HTTP kérés időzítéssel. Energy Profiler — energiafogyasztás: WakeLock, Location, Network. Részletes nyomkövetéshez használja a Systrace (Android 10+) vagy a Perfetto — rendszerkövetés mikroszekundumos pontossággal.
Az alkalmazás indítása az egyik kulcsfontosságú teljesítménymutató. Három típusra oszlik: Cold Start — az alkalmazás a semmiből indul: létrejön a folyamat, Application.onCreate (Android) / AppDelegate.applicationDidFinishLaunching (iOS), osztályok betöltése, könyvtárak inicializálása. Warm Start — a folyamat létezik, de az Activity/ViewController megsemmisült (pl. képernyő forgatásakor vagy memóriából való visszatéréskor). Hot Start — az Activity/ViewController a memóriában van, az alkalmazás egyszerűen megjelenik (váltás másik alkalmazásból).
A Cold Start a legfontosabb mérőszám. Androidon tartalmazza: (1) launch Activity — XML betöltés, View inicializálás; (2) első képkocka — idő az első megjelenítésig. Google javaslata: launch Activity < 200 ms, első képkocka < 500 ms, TTI < 5 másodperc. Cold Start optimalizálás: csökkentse az Application.onCreate-ot (korutinok a lusta inicializáláshoz), használja a SplashScreen API-t (Android 12+), halassza el a könyvtárak inicializálását (WorkManager, DI), távolítsa el a felesleges ContentProviders-eket.
iOS-en a Cold Start tartalmazza: a Mach-O bináris betöltése, dyld (dinamikus linker), Objective-C runtime inicializálása, alkalmazás delegált, első vezérlő. Chrome Custom Tabs (Android) és Universal Links (iOS) — technológiák a külső tartalom gyors megnyitásához az alkalmazásban teljes Cold Start nélkül. Javasolt a Cold Start-ot valós középkategóriás eszközökön tesztelni.
Az alkalmazás mérete a telepítés és frissítések teljesítménytényezője. Befolyásolja a konverziót: minden 10 MB 1%-kal csökkenti a konverziót. A Google Play javasolja az APK méretét 150 MB alatt; App Store — 200 MB alatt (celluláris hálózatok — 100 MB). Fő optimalizálási módszerek: kép tömörítés (WebP PNG helyett 25-35% megtakarítás), vektorizálás (VectorDrawable Androidon, SF Symbols iOS-en), nem használt kód eltávolítása (R8/ProGuard), nem használt erőforrások eltávolítása (lint → unused resources).
App Bundle (Android) — közzétételi formátum, amelyben a Google Play optimalizált APK-t generál minden eszközhöz. Az App Bundle 20-40%-kal csökkenti a letöltési méretet. Dynamic Delivery — modulok, amelyek igény szerint töltődnek le (on-demand feature modules). iOS-en a megfelelője az On-Demand Resources (ODR): az első indítás után letöltött erőforrások (játékszintek, videók).
Lusta betöltés — technika, amelyben a modulok és könyvtárak nem induláskor töltődnek be, hanem szükség szerint. Split APK (Android) és App Slicing (iOS) — az alkalmazás felosztása architektúra résekbe: arm64-v8a, x86_64. Alkalmazásméret optimalizálás — folyamatos folyamat: elemezze az APK összetételét (Analyze APK az Android Studio-ban), távolítsa el a duplikált ikonokat, használjon SVG-t több PNG-sűrűség helyett. Az IT Sectr-nél a build méret ellenőrzését beépítjük a CI/CD-be minden MR-hez.
Gyakran Ismételt Kérdések
ANR (Application Not Responding) — párbeszédpanel Androidon, amely akkor jelenik meg, ha a főszál több mint 5 másodpercig blokkolva van. Az ANR elkerüléséhez helyezze át az összes nehéz műveletet (hálózat, adatbázis, fájlfeldolgozás) háttérszálakra. A megfelelő iOS-en a frozen UI, amikor az alkalmazás nem reagál az érintésekre.
Memóriaszivárgás — amikor egy objektum nem szabadítható fel, mert még léteznek rá hivatkozások. Retain Cycle — helyzet iOS/Objective-C-ben, amikor két objektum hivatkozik egymásra (A → B → A), és az ARC egyiket sem tudja felszabadítani. Megoldás: weak/unowned hivatkozások és az időben történő callback tisztítás.
iOS-hez: Instruments (Time Profiler, Allocations, Leaks). Androidhoz: Android Profiler (CPU, Memory, Network), LeakCanary (memóriaszivárgások), StrictMode (szálsértések). Javasolt a profilozás kombinálása a fejlesztés és az integráció során.
Cold Start — az alkalmazás a semmiből indul: létrejön a folyamat, betöltődnek az osztályok, lefut az Application.onCreate. Warm Start — a folyamat létezik, de az Activity/ViewController újra létrejön. Hot Start — az Activity/ViewController már a memóriában van, csak megjelenik. A Cold Start a leglassabb (1-5 másodperc), és kritikus a felhasználói élmény szempontjából.
Fő módszerek: távolítsa el a nem használt erőforrásokat és kódot (használja az R8/ProGuard-ot), vektorizálja a képeket (VectorDrawable, SF Symbols), tömörítse a PNG/WebP-t (Android), használjon App Bundle-t APK helyett, távolítsa el a felesleges könyvtárakat, használjon lusta betöltést a modulokhoz. A méretoptimalizálás 40-60%-kal csökkentheti az APK-t.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.