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
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, 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 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.
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 (Çö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:
// Утечка: анонимный класс держит ссылку на 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, 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) | iOS | CPU, fonksiyon çağrıları, yürütme süresi | Algoritma optimizasyonu, darboğaz arama |
| Instruments (Allocations) | iOS | Bellek, nesne sayısı, retain counts | Sızıntı ve aşırı bellek tüketimi arama |
| Instruments (Leaks) | iOS | Retain cycles, bellek sızıntıları | Sürümden önce düzenli kontrol |
| Android Profiler (CPU) | Android | CPU kullanımı, iş parçacığı etkinliği, traces | Ana iş parçacığı blokajlarını bulma |
| Android Profiler (Memory) | Android | Yığın dökümü, ayırma takibi | Sızıntı bulma, nesne analizi |
| Android Profiler (Network) | Android | Trafik, hız, istek zamanlamaları | Ağ çağrıları optimizasyonu |
| LeakCanary | Android | Otomatik bellek sızıntısı tespiti | Tüm geliştirme aşamalarında |
| StrictMode | Android | Ana iş parçacığında disk/ağ, sızıntılar | Hata ayıklama yapısı |
| Traceview / Systrace | Android | Metot 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, 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.
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 (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ı — 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.
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 — 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.
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
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.