Performanța în dezvoltarea mobilă: ce este, ce metrici și cum să îmbunătățești

Autor: IT Sectr Publicat: 2026-03-25 Timp de citire: 12 min

O aplicație lentă este principalul motiv pentru care utilizatorii șterg programe. Miimi de secundă de întârziere la pornire sau la derularea unei liste reduc retenția cu zeci de procente. Performanța (performance) nu este doar viteza, ci și stabilitatea: absența ANR, a crashurilor și a scurgerilor de memorie. Acest articol acoperă toate aspectele performanței: de la gestionarea memoriei (GC, ARC) la profilarea cu instrumente. Mai multe în ghidul oficial Android Performance.

Puncte cheie

  • ANR și Crash — principalii dușmani ai experienței utilizatorului; prevenite prin fire de execuție în fundal
  • Scurgerea de memorie și Retain Cycle duc la crashuri OOM; rezolvate prin referințe slabe și utilități
  • GC (Android) și ARC (iOS) — modele de gestionare a memoriei; înțelegerea lor este critică
  • Profilarea (Instruments, Android Profiler, LeakCanary) — etapă obligatorie de dezvoltare
  • Cold Start — cea mai importantă metrică de pornire; optimizarea Application.onCreate și inițializarea leneșă
  • Dimensiunea aplicației — utilizați App Bundle, R8, VectorDrawable și WebP pentru reducerea dimensiunii

De ce încetinește aplicația?

Performanța aplicației este direct legată de jank — o întârziere vizibilă între acțiunea utilizatorului și răspunsul interfeței. Principalele cauze: blocarea firului principal (operații grele pe firul UI), redesenări frecvente ale layout-ului (overdraw), scurgeri de memorie (GC frecvent), algoritmi neoptimali (O(n²) pe seturi mari de date). Frame Rate (FPS) — numărul de cadre pe secundă. Pentru o experiență confortabilă sunt necesari 60 FPS stabili (Android) sau 120 FPS (iPhone Pro, iPad Pro). VSync sincronizează randarea cu rata de reîmprospătare a ecranului.

Jank apare când randarea unui singur cadru depășește 16,6 ms (pentru 60 FPS) sau 8,3 ms (pentru 120 FPS). Profilarea GPU (Profile GPU Rendering pe Android, Core Animation pe iOS) arată care etape de randare consumă cel mai mult timp. Etape principale: Layout (aranjarea elementelor), Draw (desenarea), Display (transferul în bufferul de cadre). Cea mai frecventă problemă este inflația layout-ului în XML, mai ales când se utilizează ConstraintLayout imbricat complex.

Time-to-Interactive (TTI) — timpul necesar pentru ca aplicația să fie complet gata de interacțiune. TTI include Cold Start, încărcarea datelor și inițializarea bibliotecilor. Google recomandă TTI sub 5 secunde, Apple — sub 2 secunde pentru ecranele principale. Lazy Loading — tehnică de încărcare întârziată a conținutului și bibliotecilor, critică pentru îmbunătățirea TTI. La IT Sectr, folosim inițializarea leneșă implicit în toate proiectele.

ANR și Crash

ANR și Crash sunt principalii dușmani ai performanței aplicațiilor mobile. ANR (Application Not Responding) — fereastră de dialog pe Android care apare dacă firul principal este blocat mai mult de 5 secunde. Cauze: cereri de rețea sincrone pe firul UI, lucrul cu baza de date fără corutine, decodificarea bitmap-urilor mari fără downsampling, deadlock pe firul principal. Stiva de apeluri ANR este salvată în /data/anr/traces.txt și permite determinarea locației exacte a blocării.

Crash — terminarea neașteptată a aplicației. Pe Android — o Exception (Java/Kotlin) sau Signal (cod nativ). Pe iOS — NSException sau semnal (EXC_BAD_ACCESS — acces la memorie eliberată). Instrumente de raportare a crashurilor: Firebase Crashlytics, Sentry, BugSnag. Acestea colectează stacktrace, date despre dispozitiv și pași de reproducere. Stack Overflow — depășirea stivei de apeluri prin recursivitate infinită. OutOfMemoryError — când heap-ul este plin.

StrictMode — instrument Android pentru detectarea încălcărilor de securitate a firelor de execuție. Permite stabilirea de reguli: ThreadPolicy (interzice disc/rețea pe firul principal), VmPolicy (detectează scurgeri de Activity, SQLite, CloseGuard). StrictMode ar trebui activat doar în compilările de debug — în versiunea de lansare nu ar trebui să funcționeze. Pe iOS, echivalentul este Main Thread Checker (Xcode), care detectează automat apelurile UIKit care nu sunt pe firul principal.

Gestionarea memoriei (GC, ARC, Retain Cycle)

Scurgerea de memorie

O scurgere de memorie (Memory Leak) apare atunci când un obiect rămâne în memorie chiar dacă aplicația nu îl mai folosește. Aceasta reduce direct performanța aplicației. Pe Android, GC (Garbage Collection) nu poate colecta un obiect dacă există o referință puternică la el. Cauze tipice: referințe statice la Activity, callback/observatori neanulați, clase interne cu referință implicită la clasa externă, Handler cu mesaje necurățate. LeakCanary — bibliotecă pentru detectarea automată a scurgerilor.

Retain Cycle (Ciclu de reținere)

ARC (Automatic Reference Counting) — model de gestionare a memoriei pe iOS. Fiecare obiect are un contor de referințe (retain count). Când contorul ajunge la zero, memoria este eliberată. Un Retain Cycle apare când două obiecte mențin referințe puternice unul către celălalt (A → B și B → A). ARC nu va zerouri contoarele niciodată. Soluție: referințe slabe (weak) sau fără proprietar (unowned). Weak se anulează automat (devine nil) la eliberarea obiectului. Unowned nu se anulează dar garantează că obiectul este viu.

GC vs ARC

GC (Garbage Collection) funcționează pe Android (Java/Kotlin). GC întrerupe periodic execuția (pauză Stop-the-World) pentru a găsi și elibera obiectele inaccesibile. Declanșarea GC: când heap-ul atinge un anumit procent de umplere. ARC funcționează pe iOS (Swift/Objective-C) și nu are pauze — contoarele sunt actualizate atomic la fiecare atribuire. ARC este mai previzibil, dar poate acumula operații retain/release excesive la frecvență ridicată de atribuire.

Referință slabă (Weak Reference) și referință puternică (Strong Reference) — tipul de referință determină dacă GC/ARC poate elibera obiectul. Strong Reference — obiectul nu va fi colectat cât timp există această referință. Weak Reference — GC/ARC poate colecta obiectul; referința slabă devine nil (în Swift/Java WeakReference). Unowned Reference (Swift) — nu se anulează la eliberare; accesarea ei după moartea obiectului provoacă un crash. Pe Android se folosește java.lang.ref.WeakReference pentru referințe slabe.

Exemplu de detectare a unei scurgeri pe Android cu LeakCanary:

kotlin
// Утечка: анонимный класс держит ссылку на 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")
    }
}

Profilarea (Instruments, Android Profiler)

Profilarea este procesul de măsurare a performanței aplicației: CPU, memorie, rețea, consum de energie. Fără profilare, optimizarea oarbă este inutilă — nu veți ști ce parte a codului este de fapt lentă.

Instrument Platformă Măsoară Când să utilizați
Instruments (Time Profiler)iOSCPU, apeluri de funcții, timp de execuțieOptimizarea algoritmilor, căutarea blocajelor
Instruments (Allocations)iOSMemorie, număr de obiecte, retain countsCăutarea scurgerilor și consumului excesiv de memorie
Instruments (Leaks)iOSRetain cycles, scurgeri de memorieVerificare regulată înainte de lansare
Android Profiler (CPU)AndroidUtilizare CPU, activitate fire, tracesCăutarea blocărilor firului principal
Android Profiler (Memory)AndroidHeap dump, urmărirea alocărilorCăutarea scurgerilor, analiza obiectelor
Android Profiler (Network)AndroidTrafic, viteză, temporizări cereriOptimizarea apelurilor de rețea
LeakCanaryAndroidDetectarea automată a scurgerilor de memorieÎn toate etapele de dezvoltare
StrictModeAndroidDisc/rețea pe firul principal, scurgeriCompilare de debug
Traceview / SystraceAndroidUrmărirea metodelor, evenimente de sistemAnaliză aprofundată a latenței

Instruments (Xcode) — cel mai puternic instrument pentru iOS. Time Profiler arată care funcții consumă cel mai mult CPU. Allocations urmărește crearea și eliberarea obiectelor. Leaks găsește automat retain cycles. Pași de profilare: (1) lansați Instruments; (2) selectați șablonul (Time Profiler pentru CPU); (3) executați scenariul problemtic; (4) analizați stiva de apeluri — coloana cea mai largă este funcția cea mai "fierbinte".

Android Profiler este integrat în Android Studio (View → Tool Windows → Profiler). CPU Profiler arată încărcarea fiecărui fir. Memory Profiler — heap dump și urmărirea alocărilor. Network Profiler — toate cererile HTTP cu temporizări. Energy Profiler — consum de energie: WakeLock, Location, Network. Pentru urmărire detaliată se folosește Systrace (Android 10+) sau Perfetto — urmărirea sistemului cu precizie de microsecundă.

Pornirea aplicației (Cold/Warm/Hot Start)

Pornirea aplicației este unul dintre indicatorii cheie de performanță. Se împarte în trei tipuri: Cold Start — aplicația pornește de la zero: se creează procesul, Application.onCreate (Android) / AppDelegate.applicationDidFinishLaunching (iOS), încărcarea claselor, inițializarea bibliotecilor. Warm Start — procesul există, dar Activity/ViewController este distrus (de exemplu, la rotirea ecranului sau la revenirea din memorie). Hot Start — Activity/ViewController este în memorie, aplicația este pur și simplu afișată (comutare de la o altă aplicație).

Cold Start este cea mai importantă metrică. Pe Android include: (1) lansarea Activity — încărcare XML, inițializare View; (2) primul cadru — timpul până la prima randare. Google recomandă: lansare Activity < 200 ms, primul cadru < 500 ms, TTI < 5 secunde. Optimizarea Cold Start: reduceți Application.onCreate (corutine pentru inițializare leneșă), utilizați SplashScreen API (Android 12+), amânați inițializarea bibliotecilor (WorkManager, DI), eliminați ContentProviders inutile.

Pe iOS, Cold Start include: încărcarea binarului Mach-O, dyld (linker-ul dinamic), inițializarea runtime-ului Objective-C, delegatul aplicației, primul controler. Chrome Custom Tabs (Android) și Universal Links (iOS) — tehnologii pentru deschiderea rapidă a conținutului extern în aplicație fără un Cold Start complet. Se recomandă testarea Cold Start pe dispozitive reale de gamă medie.

Optimizarea dimensiunii

Dimensiunea aplicației este un factor de performanță pentru instalare și actualizări. Afectează conversia: fiecare 10 MB reduce conversia cu 1%. Google Play recomandă dimensiunea APK sub 150 MB; App Store — sub 200 MB (rețele celulare — 100 MB). Principalele metode de optimizare: compresia imaginilor (WebP în loc de PNG economisește 25-35%), vectorizarea (VectorDrawable pe Android, SF Symbols pe iOS), eliminarea codului neutilizat (R8/ProGuard), eliminarea resurselor neutilizate (lint → unused resources).

App Bundle (Android) — format de publicare în care Google Play generează un APK optimizat pentru fiecare dispozitiv. App Bundle reduce dimensiunea descărcării cu 20-40%. Dynamic Delivery — module descărcate la cerere (on-demand feature modules). Pe iOS, echivalentul este On-Demand Resources (ODR): resurse descărcate după prima lansare (niveluri de joc, videoclipuri).

Lazy Loading — tehnică în care modulele și bibliotecile nu sunt încărcate la pornire, ci sunt încărcate după necesitate. Split APK (Android) și App Slicing (iOS) — împărțirea aplicației în sloturi de arhitectură: arm64-v8a, x86_64. Optimizarea dimensiunii aplicației — un proces continuu: analizați compoziția APK (Analyze APK în Android Studio), eliminați iconițele duplicate, utilizați SVG în loc de mai multe densități PNG. La IT Sectr, includem verificarea dimensiunii build-ului în CI/CD pentru fiecare MR.

Întrebări frecvente

Ce este ANR și cum să îl evitați?

ANR (Application Not Responding) — fereastră de dialog pe Android care apare dacă firul principal este blocat mai mult de 5 secunde. Pentru a evita ANR, mutați toate operațiile grele (rețea, bază de date, procesare fișiere) în fire de execuție de fundal. Echivalentul pe iOS este frozen UI, când aplicația nu mai răspunde la atingeri.

Ce este o scurgere de memorie și un Retain Cycle?

O scurgere de memorie apare atunci când un obiect nu poate fi eliberat deoarece mai există referințe la el. Un Retain Cycle este o situație în iOS/Objective-C în care două obiecte se referă unul la altul (A → B → A) și ARC nu poate elibera niciunul. Soluție: referințe weak/unowned și curățarea la timp a callback-urilor.

Ce instrumente să utilizați pentru profilare?

Pentru iOS: Instruments (Time Profiler, Allocations, Leaks). Pentru Android: Android Profiler (CPU, Memory, Network), LeakCanary (scurgeri de memorie), StrictMode (încălcări ale firelor). Se recomandă combinarea profilării în timpul dezvoltării și integrării.

Cu ce diferă Cold Start de Warm Start și Hot Start?

Cold Start — aplicația pornește de la zero: se creează procesul, se încarcă clasele, se execută Application.onCreate. Warm Start — procesul există, dar Activity/ViewController este recreat. Hot Start — Activity/ViewController este deja în memorie, pur și simplu afișat. Cold Start este cel mai lent (1-5 secunde) și este critic pentru experiența utilizatorului.

Cum să reduceți dimensiunea unei aplicații mobile?

Metode principale: eliminați resursele și codul neutilizat (utilizați R8/ProGuard), vectorizați imaginile (VectorDrawable, SF Symbols), comprimați PNG/WebP (Android), utilizați App Bundle în loc de APK, eliminați bibliotecile inutile, utilizați Lazy Loading pentru module. Optimizarea dimensiunii poate reduce APK-ul cu 40-60%.

Rezumat

  • ANR și Crash — principalele probleme de stabilitate; rezolvate prin fire de execuție de fundal și raportoare de crash
  • Scurgerea de memorie și Retain Cycle — principalele cauze ale OOM; rezolvate prin referințe slabe și LeakCanary
  • GC (pauze Stop-the-World) vs ARC (fără pauze, dar retain cycles) — modele de memorie diferite
  • Profilarea — etapă obligatorie: Instruments (iOS), Android Profiler, LeakCanary, StrictMode
  • Cold Start — metrică cheie; optimizați Application.onCreate și inițializarea leneșă
  • App Bundle și WebP/VectorDrawable — instrumente principale pentru reducerea dimensiunii cu 20-60%
  • Performanța este un proces continuu, nu o activitate unică; integrați metricile în CI/CD

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul