Mobil Geliştirmede Performans: nedir, hangi metrikler ve nasıl iyileştirilir

Yazar: IT Sectr Yayınlanma: 2026-03-25 Okuma süresi: 12 dk

Yavaş bir uygulama, kullanıcıların programları silmesinin ana nedenidir. Başlatma sırasında veya liste kaydırma sırasında milisaniyelik gecikmeler, kullanıcı tutma oranını yüzde onlarca düşürür. Performans sadece hız değil, aynı zamanda kararlılıktır: ANR, çökme ve bellek sızıntısı olmaması. Bu makale, bellek yönetiminden (GC, ARC) araçlarla profillemeye kadar performansın tüm yönlerini kapsar. Daha fazla bilgi için resmi Android Performance kılavuzuna bakın.

Ana Noktalar

  • ANR ve Çökmeler, kullanıcı deneyiminin ana düşmanlarıdır; arka plan iş parçacıklarıyla önlenir
  • Bellek Sızıntısı ve Retain Cycle OOM çökmelerine yol açar; zayıf referanslar ve yardımcı araçlarla çözülür
  • GC (Android) ve ARC (iOS) bellek yönetimi modelleridir; çalışma şekillerini anlamak kritiktir
  • Profilleme (Instruments, Android Profiler, LeakCanary) zorunlu bir geliştirme aşamasıdır
  • Soğuk Başlatma en önemli başlatma metriğidir; Application.onCreate optimizasyonu ve tembel başlatma
  • Uygulama Boyutu — boyutu azaltmak için App Bundle, R8, VectorDrawable ve WebP kullanın

Uygulama neden yavaş?

Uygulama performansı doğrudan jank (kullanıcı eylemi ile UI yanıtı arasındaki fark edilir gecikme) ile ilişkilidir. Ana nedenler: Ana iş parçacığının bloke edilmesi (UI iş parçacığında ağır işlemler), sık layout yeniden çizimleri (overdraw), bellek sızıntıları (sık GC), optimal olmayan algoritmalar (büyük verilerde O(n²)). Kare Hızı (FPS) — saniyedeki kare sayısı. Rahat bir deneyim için sabit 60 FPS (Android) veya 120 FPS (iPhone Pro, iPad Pro) gerekir. VSync, işlemeyi ekran yenileme hızıyla senkronize eder.

Jank, tek bir karenin işlenmesi 16,6 ms'yi (60 FPS için) veya 8,3 ms'yi (120 FPS için) aştığında oluşur. GPU profillemesi (Android'de Profile GPU Rendering, iOS'ta Core Animation), işlemenin hangi aşamalarının en çok zaman aldığını gösterir. Ana aşamalar: Layout (öğelerin yerleştirilmesi), Draw (çizim), Display (kare arabelleğine aktarma). En yaygın sorun, özellikle karmaşık iç içe ConstraintLayout kullanıldığında XML'de layout şişmesidir.

Time-to-Interactive (TTI) — uygulamanın tamamen etkileşime hazır hale gelmesi için geçen süre. TTI, Soğuk Başlatma, veri yükleme ve kütüphane başlatmayı içerir. Google, TTI'nin 5 saniyenin altında olmasını önerir; Apple ise ana ekranlar için 2 saniyenin altında olmasını önerir. Tembel Yükleme — içerik ve kütüphanelerin gecikmeli yüklenmesi tekniği, TTI'yı iyileştirmek için kritiktir. IT Sectr'de tüm projelerde varsayılan olarak tembel başlatma kullanıyoruz.

ANR ve Çökmeler

ANR ve çökmeler, mobil uygulama performansının ana düşmanlarıdır. ANR (Application Not Responding) — ana iş parçacığı 5 saniyeden fazla bloke olursa Android'de görünen iletişim kutusu. Nedenler: UI iş parçacığında senkron ağ istekleri, coroutine olmadan veritabanı çalışması, downsampling olmadan büyük bitmap kod çözme, ana iş parçacığında deadlock. ANR çağrı yığını /data/anr/traces.txt dosyasına kaydedilir ve tam blokaj konumunu belirlemeye olanak tanır.

Çökme — beklenmeyen uygulama sonlanması. Android'de — Exception (Java/Kotlin) veya Signal (yerel kod). iOS'ta — NSException veya sinyal (EXC_BAD_ACCESS — serbest bırakılmış belleğe erişim). Çökme Raporlama Araçları: Firebase Crashlytics, Sentry, BugSnag. Bunlar yığın izi, cihaz verileri ve yeniden oluşturma adımlarını toplar. Stack Overflow — sonsuz özyineleme nedeniyle çağrı yığını taşması. OutOfMemoryError — yığın (heap) dolduğunda.

StrictMode — iş parçacığı güvenliği ihlallerini tespit etmek için Android aracı. Kurallar belirlemeye izin verir: ThreadPolicy (ana iş parçacığında disk/ağı yasakla), VmPolicy (Activity, SQLite, CloseGuard sızıntılarını tespit et). StrictMode yalnızca hata ayıklama yapılarında etkinleştirilmelidir — sürümde çalışmamalıdır. iOS'taki karşılığı, ana iş parçacığında olmayan UIKit çağrılarını otomatik olarak algılayan Main Thread Checker'dır (Xcode).

Bellek Yönetimi (GC, ARC, Retain Cycle)

Bellek Sızıntısı

Bellek sızıntısı (Memory Leak) — bir nesnenin, uygulama onu artık kullanmasa bile bellekte kalması durumudur. Bu, uygulama performansını doğrudan düşürür. Android'de GC (Çöp Toplama), bir nesneye güçlü bir referans varsa onu toplayamaz. Tipik nedenler: Activity'ye statik referanslar, temizlenmemiş geri çağırmalar/gözlemciler, dış sınıfa örtük referansı olan iç sınıflar, temizlenmemiş mesajları olan Handler. LeakCanary — otomatik sızıntı tespiti için kütüphane.

Retain Cycle (Tutma Döngüsü)

ARC (Automatic Reference Counting) — iOS'ta bellek yönetimi modeli. Her nesnenin bir referans sayacı (retain count) vardır. Sayaç sıfıra ulaştığında bellek serbest bırakılır. Retain Cycle, iki nesne birbirine güçlü referanslar tuttuğunda oluşur (A → B ve B → A). ARC, sayaçları asla sıfırlamaz. Çözüm: zayıf (weak) veya sahipsiz (unowned) referanslar. Weak, nesne serbest bırakıldığında otomatik olarak nil olur. Unowned nil olmaz ancak nesnenin canlı olduğunu garanti eder.

GC vs ARC

GC (Çöp Toplama) Android'de (Java/Kotlin) çalışır. GC, ulaşılamaz nesneleri bulmak ve serbest bırakmak için periyodik olarak yürütmeyi duraklatır (Stop-the-World duraklaması). GC Tetikleyicisi: yığın belirli bir yüzdeye ulaştığında. ARC iOS'ta (Swift/Objective-C) çalışır ve duraklaması yoktur — sayaçlar her atamada atomik olarak güncellenir. ARC daha öngörülebilirdir ancak yüksek atama sıklığında aşırı retain/release işlemleri biriktirebilir.

Zayıf Referans (Weak Reference) ve Güçlü Referans (Strong Reference) — referans türü, GC/ARC'nin nesneyi serbest bırakıp bırakamayacağını belirler. Strong Reference — bu referans var olduğu sürece nesne toplanmayacaktır. Weak Reference — GC/ARC nesneyi toplayabilir; zayıf referans nil olur (Swift/Java WeakReference'da). Unowned Reference (Swift) — serbest bırakıldığında nil olmaz; nesne öldükten sonra ona erişmek çökmeye neden olur. Android'de zayıf referanslar için java.lang.ref.WeakReference kullanılır.

LeakCanary ile Android'de sızıntı tespiti örneği:

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")
    }
}

Profilleme (Instruments, Android Profiler)

Profilleme, uygulama performansını (CPU, bellek, ağ, güç tüketimi) ölçme sürecidir. Profilleme olmadan kör optimizasyon işe yaramaz — kodun hangi bölümünün gerçekten yavaş olduğunu bilemezsiniz.

Araç Platform Ölçer Ne zaman kullanılır
Instruments (Time Profiler)iOSCPU, fonksiyon çağrıları, yürütme süresiAlgoritma optimizasyonu, darboğaz arama
Instruments (Allocations)iOSBellek, nesne sayısı, retain countsSızıntı ve aşırı bellek tüketimi arama
Instruments (Leaks)iOSRetain cycles, bellek sızıntılarıSürümden önce düzenli kontrol
Android Profiler (CPU)AndroidCPU kullanımı, iş parçacığı etkinliği, tracesAna iş parçacığı blokajlarını bulma
Android Profiler (Memory)AndroidYığın dökümü, ayırma takibiSızıntı bulma, nesne analizi
Android Profiler (Network)AndroidTrafik, hız, istek zamanlamalarıAğ çağrıları optimizasyonu
LeakCanaryAndroidOtomatik bellek sızıntısı tespitiTüm geliştirme aşamalarında
StrictModeAndroidAna iş parçacığında disk/ağ, sızıntılarHata ayıklama yapısı
Traceview / SystraceAndroidMetot izleme, sistem olaylarıDerin gecikme analizi

Instruments (Xcode) — iOS için en güçlü araç. Time Profiler, hangi fonksiyonların en çok CPU tükettiğini gösterir. Allocations, nesne oluşturma ve serbest bırakmayı izler. Leaks, otomatik olarak retain cycle'ları bulur. Profilleme adımları: (1) Instruments'ı başlatın; (2) şablon seçin (CPU için Time Profiler); (3) sorunlu senaryoyu çalıştırın; (4) çağrı yığınını analiz edin — en geniş sütun en "sıcak" fonksiyondur.

Android Profiler, Android Studio'ya entegredir (View → Tool Windows → Profiler). CPU Profiler, her iş parçacığının yükünü gösterir. Memory Profiler — yığın dökümü ve ayırma takibi. Network Profiler — zamanlamalarla tüm HTTP istekleri. Energy Profiler — güç tüketimi: WakeLock, Location, Network. Ayrıntılı izleme için Systrace (Android 10+) veya Perfetto — mikrosaniye hassasiyetinde sistem izleme kullanılır.

Uygulama Başlatma (Soğuk/Ilık/Sıcak Başlatma)

Uygulama başlatma, temel performans göstergelerinden biridir. Üç türe ayrılır: Soğuk Başlatma — uygulama sıfırdan başlar: süreç oluşturulur, Application.onCreate (Android) / AppDelegate.applicationDidFinishLaunching (iOS), sınıf yükleme, kütüphane başlatma. Ilık Başlatma — süreç var ancak Activity/ViewController yok edilmiştir (örneğin, ekran döndürme veya bellekten dönüş). Sıcak Başlatma — Activity/ViewController bellekte, uygulama sadece görüntülenir (başka bir uygulamadan geçiş).

Soğuk Başlatma en önemli metriktir. Android'de şunları içerir: (1) launch Activity — XML yükleme, View başlatma; (2) ilk kare — ilk işlemeye kadar geçen süre. Google önerir: launch Activity < 200 ms, ilk kare < 500 ms, TTI < 5 saniye. Soğuk Başlatma optimizasyonu: Application.onCreate'u azaltın (tembel başlatma için coroutine), SplashScreen API (Android 12+) kullanın, kütüphane başlatmayı erteleyin (WorkManager, DI), gereksiz ContentProviders'ları kaldırın.

iOS'ta Soğuk Başlatma şunları içerir: Mach-O ikili dosyası yükleme, dyld (dinamik bağlayıcı), Objective-C çalışma zamanı başlatma, uygulama delegate'i, ilk denetleyici. Chrome Custom Tabs (Android) ve Universal Links (iOS) — tam Soğuk Başlatma olmadan uygulamada harici içeriği hızlıca açma teknolojileri. Soğuk Başlatma'nın gerçek orta sınıf cihazlarda test edilmesi önerilir.

Boyut Optimizasyonu

Uygulama boyutu, kurulum ve güncellemeler için bir performans faktörüdür. Dönüşümü etkiler: her 10 MB dönüşümü %1 azaltır. Google Play önerir APK boyutu 150 MB'ın altında; App Store — 200 MB'ın altında (hücresel ağlar — 100 MB). Ana optimizasyon yöntemleri: görüntü sıkıştırma (PNG yerine WebP %25-35 tasarruf), vektörleştirme (Android'de VectorDrawable, iOS'ta SF Symbols), kullanılmayan kodu kaldırma (R8/ProGuard), kullanılmayan kaynakları kaldırma (lint → unused resources).

App Bundle (Android) — Google Play'in her cihaz için optimize edilmiş APK oluşturduğu yayınlama biçimi. App Bundle, indirme boyutunu %20-40 azaltır. Dynamic Delivery — talep üzerine indirilen modüller (on-demand feature modules). iOS'taki karşılığı On-Demand Resources (ODR): ilk başlatmadan sonra indirilen kaynaklar (oyun seviyeleri, videolar).

Tembel Yükleme — modüllerin ve kütüphanelerin başlatma sırasında değil, ihtiyaç duyuldukça yüklendiği teknik. Split APK (Android) ve App Slicing (iOS) — uygulamayı mimari yuvalara bölme: arm64-v8a, x86_64. Uygulama Boyutu Optimizasyonu — sürekli bir süreç: APK bileşimini analiz edin (Android Studio'da Analyze APK), yinelenen simgeleri kaldırın, birden çok PNG yoğunluğu yerine SVG kullanın. IT Sectr'de her MR için CI/CD'de derleme boyutu kontrolünü dahil ediyoruz.

Sıkça Sorulan Sorular

ANR nedir ve nasıl önlenir?

ANR (Application Not Responding) — ana iş parçacığı 5 saniyeden fazla bloke olursa Android'de görünen iletişim kutusu. ANR'yi önlemek için tüm ağır işlemleri (ağ, veritabanı, dosya işleme) arka plan iş parçacıklarına taşıyın. iOS'taki karşılığı, uygulamanın dokunmalara yanıt vermeyi bıraktığı donmuş UI'dır.

Bellek Sızıntısı ve Retain Cycle nedir?

Bellek Sızıntısı — bir nesneye referanslar var olduğu için serbest bırakılamaması. Retain Cycle — iOS/Objective-C'de iki nesnenin birbirine referans verdiği (A → B → A) ve ARC'nin hiçbirini serbest bırakamadığı durum. Çözüm: weak/unowned referanslar ve zamanında geri çağırma temizliği.

Profilleme için hangi araçlar kullanılır?

iOS için: Instruments (Time Profiler, Allocations, Leaks). Android için: Android Profiler (CPU, Memory, Network), LeakCanary (bellek sızıntıları), StrictMode (iş parçacığı ihlalleri). Geliştirme ve entegrasyon sırasında profillemenin birleştirilmesi önerilir.

Soğuk Başlatma, Ilık Başlatma ve Sıcak Başlatma arasındaki fark nedir?

Soğuk Başlatma — uygulama sıfırdan başlar: süreç oluşturulur, sınıflar yüklenir, Application.onCreate çalışır. Ilık Başlatma — süreç var ancak Activity/ViewController yeniden oluşturulur. Sıcak Başlatma — Activity/ViewController zaten bellekte, sadece görüntülenir. Soğuk Başlatma en yavaşıdır (1-5 saniye) ve kullanıcı deneyimi için kritiktir.

Mobil uygulama boyutu nasıl azaltılır?

Ana yöntemler: kullanılmayan kaynakları ve kodu kaldırın (R8/ProGuard kullanın), görüntüleri vektörleştirin (VectorDrawable, SF Symbols), PNG/WebP sıkıştırın (Android), APK yerine App Bundle kullanın, gereksiz kütüphaneleri kaldırın, modüller için Tembel Yükleme kullanın. Boyut optimizasyonu APK'yı %40-60 oranında azaltabilir.

Özet

  • ANR ve Çökmeler — ana kararlılık sorunları; arka plan iş parçacıkları ve çökme raporlayıcılarıyla çözülür
  • Bellek Sızıntısı ve Retain Cycle — OOM'nin ana nedenleri; zayıf referanslar ve LeakCanary ile çözülür
  • GC (Stop-the-World duraklamaları) vs ARC (duraklama yok ancak retain cycle'lar) — farklı bellek modelleri
  • Profilleme — zorunlu aşama: Instruments (iOS), Android Profiler, LeakCanary, StrictMode
  • Soğuk Başlatma — ana metrik; Application.onCreate optimizasyonu ve tembel başlatma
  • App Bundle ve WebP/VectorDrawable — boyutu %20-60 azaltmak için ana araçlar
  • Performans sürekli bir süreçtir, tek seferlik bir etkinlik değildir; metrikleri CI/CD'ye entegre edin

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış