ANDROID PERFORMANS PROFILER ANR
Kullanıcı uygulamayı açıyor, ana sayfadaki butona basıyor. Bir saniye, iki, üç... Beş. Ekran hâlâ tıklamaya cevap vermiyor. Sonra Android sistemi araya giriyor: "Uygulama yanıt vermiyor. Kapat veya bekle?" Bu mesaj, Play Store yorumlarının altında hızla "uygulama donuyor" şikayetlerine dönüşür. Çıktığı yerde fark edilmezse, gelir kaybı ve düşük puan olarak geri döner. ANR — Application Not Responding — Android'in en görünür kalite sinyallerinden biridir. Bu yazı, Android Studio'nun yerleşik Performance Profiler aracıyla ANR sebebini nasıl avladığınızı, CPU ve bellek darboğazlarını okuma yöntemini ve üretime çıkmadan önce alabileceğiniz önlemleri pratik bakışla anlatır.
ANR Neye Göre Tetiklenir
Android sistemi ana thread'i (UI thread) sürekli dinler. Belirli zaman pencerelerinde ana thread'in cevap vermesini bekler; veremezse ANR diyalogu açar. Üç ana eşik vardır:
- Activity / Input dispatching: 5 saniye boyunca dokunma veya tuş olayına cevap yoksa
- Broadcast Receiver: onReceive ön planda 10, arka planda 60 saniye içinde tamamlanmazsa
- Service: onStartCommand veya onBind ön planda 20, arka planda 200 saniye içinde dönmezse
Ana thread'in neden bloke olduğu kullanıcıya yansımaz; sistem sadece "yanıt yok" der. Sebebi bulmak geliştiriciye düşer. Çoğu ANR'in arkasında klasik birkaç hata vardır: ana thread'de ağ çağrısı, ana thread'de büyük SQL sorgusu, senkron dosya okuma, lock contention veya rekürsif bir döngü. Profiler bu kategorileri ayırt etmek için tasarlanmıştır.
Android Studio Profiler — Üç Pencere
Android Studio'nun View > Tool Windows > Profiler altından açılan pencere üç ana izleyiciyi tek timeline üzerinde gösterir:
- CPU Profiler: Hangi thread, ne kadar süre, hangi metodu çalıştırıyor
- Memory Profiler: Heap kullanımı, allocation hızı, GC olayları
- Network Profiler: Açılan bağlantılar, transfer hızları, request ve response zaman çizgisi
Üçü ortak bir zaman ekseninde durduğu için tek bir tıklama olayını tüm boyutlarıyla okuyabilirsiniz. Profiler'ı kullanmak için cihazın gerçek olması şart değil; emülatör de izleme verisini yayınlar. Yalnızca debuggable build'lerde tam izleme açıktır; release build profil değerleri kabaca verir.

CPU Profiler — Ana Thread'i Kim Bloke Ediyor
Bir ANR şüphesinde ilk durulacak yer CPU Profiler'dır. Profiler çubuğunda Record butonuna basıp şikayet edilen senaryoyu tekrarlatırsınız. Sonuçlar dört kayıt modunda alınır:
- Sample Java/Kotlin Methods: Düşük overhead, ANR avı için varsayılan tercih
- Trace Java/Kotlin Methods: Her metod giriş-çıkışı kaydeder, doğru ama yavaşlatır
- Sample C/C++ Functions: NDK kodu için
- System Trace: Çekirdek seviyesinde zamanlama, Perfetto formatında
Kaydı durdurduğunuzda Flame Chart ve Call Chart sekmeleri açılır. ANR'ye yol açan metot çoğu zaman flame grafiğinde geniş yatay bir blok olarak öne çıkar. Örneğin tıklama anında ana thread'de duran bir Cursor.moveToNext() çağrısı, beş saniyenin önemli bir kısmını yutuyorsa orada görülür. Aynı metodu yarı saatlik bir gözlemde 200 kez gören gözle bulamazsınız; flame chart bunu görünür kılar. Resmi belgelerin başlangıç noktası için Android Studio Profiler dokümantasyonu kapsamlı bir başlangıç noktasıdır.
Pratik Bir Örnek
Aşağıdaki kod ana thread'de SQLite sorgusu çalıştırdığı için ANR riskini taşır:
// kötü — ana thread'de I/O
button.setOnClickListener {
val cursor = db.rawQuery("SELECT * FROM logs", null)
while (cursor.moveToNext()) { /* ... */ }
}Doğru çözüm viewModelScope içinde Dispatchers.IO bağlamına almaktır:
button.setOnClickListener {
viewModelScope.launch(Dispatchers.IO) {
val rows = db.logDao().getAll()
withContext(Dispatchers.Main) { adapter.submitList(rows) }
}
}Coroutines ve thread yönetimi konusuna toplu bakmak isteyenler kapsamlı Android Kotlin eğitimi üzerinden yapılandırılmış bir patikadan ilerleyebilir.

Memory Profiler — GC Tetiklenen Donmalar
Bütün ANR'ler CPU darboğazından gelmez. Bazıları Garbage Collector'ün ana thread'i durdurmasından kaynaklanır. Bir liste ekranında her satır için gereksiz bir Bitmap üretildiğinde heap hızla dolar; GC tetiklendiğinde ana thread "stop-the-world" pause yaşar. Memory Profiler bu örüntüyü iki sinyalle yakalatır:
- Allocation rate grafiğinde sürekli yüksek tepe (saniyede MB'larca tahsis)
- GC olayları timeline'da sık ve uzun çubuklar olarak
Heap dump alıp Object Allocations görünümünde sıralandığında problemli sınıf çoğu zaman doğrudan listenin başında çıkar. Activity leak'leri ise Leaks sekmesinde otomatik gösterilir — bu da uzun vadeli ANR tetikleyicisidir çünkü heap zamanla doldukça pause süreleri uzar.
Sistem İzleri ve traces.txt
Üretimde ANR oluştuğunda Android sistemi /data/anr/traces.txt dosyasına o anda tüm thread'lerin stack trace'ini yazar. Bu dosya Profiler kadar görsel değil ama hayati bilgi taşır:
- Ana thread hangi metodda kilitliydi
- Hangi thread hangi lock'u bekliyordu
- Native frame'ler varsa hangi C++ çağrısı yapılıyordu
Cihazdan adb pull /data/anr/traces.txt ile alınır; Play Console'un Android Vitals sekmesi de aynı veriyi anonim olarak toplayıp ANR oranlarını gösterir. Vitals'taki "User-perceived ANR rate" %0.47'nin altında olmalıdır; bu eşik aşıldığında Play Store görünürlüğü düşer.
ANR'leri Üretime Çıkmadan Yakalamak
Profiler sorun çıktıktan sonra tanı koyar; daha iyisi sorunun hiç çıkmamasıdır. Birkaç pratik önlem üretimde ANR'leri ciddi biçimde azaltır:
- StrictMode: Debug build'lerde ana thread'de I/O, network veya custom slow call yakalandığında log bırakır veya uygulamayı çökertir
- Linter kuralları: Android Studio "Main thread network" gibi uyarıları varsayılan olarak gösterir, açık tutun
- WorkManager ve Coroutines: Uzun süren tüm işler için zorunlu kullanım
- Macrobenchmark: Startup, scrolling gibi senaryoları otomatik ölçer, CI'ye bağlanabilir
- Pre-launch report: Play Console internal track'inde otomatik ANR raporu çıkar
ANR'lerin tek bir kök sebebi yoktur, profilleme alışkanlığı vardır. Çoğu deneyimli Android geliştiricisi yeni özelliği bitirir bitirmez Profiler'ı açıp aynı senaryoyu kaydeder. Bu beş dakikalık alışkanlık, üretimde saatlerce süren sorun avından çok daha ucuza mal olur.



