RAM Dolunca Android Ne Yapar?
Sınırlı Bir Kaynağı Yönetmenin Sanatı
Masaüstü bilgisayarlar bellek baskısıyla karşılaştığında başvurdukları bir çözüm var: swap. Diskin bir bölümünü sanal bellek olarak kullanır, belleğin bir kısmını diske yazar ve alanı serbest bırakır. Yavaşlatır ama sistemi ayakta tutar.
Mobil cihazlar bu lüksü büyük ölçüde barındırmaz. Flash depolama, masaüstündeki sabit diskten çok daha fazla yıpranmaya duyarlıdır ve sürekli swap için uygun değildir. Bellek baskısı arttığında Android farklı bir strateji izler — ve bu stratejiyi anlamak, uygulamalarınızın neden bazen beklenmedik biçimde davrandığını açıklar.
Android'in Bellek Yönetim Felsefesi
Android'in bellek yönetiminin temel prensibi şudur: Boş bellek israf edilen bellektir.
Masaüstü düşüncesiyle bakıldığında bu ilginç görünebilir. Ama Android, boşta duran RAM'i aktif olarak kullanmayı tercih eder. Arka planda bekleyen uygulamaları bellekte tutmak, kullanıcı o uygulamaya döndüğünde sıfırdan başlatmaktan çok daha hızlı bir deneyim sunar.
Bu yüzden Android sistemi kasıtlı olarak RAM'i dolu tutmaya çalışır. Bellek baskısı yaşandığında ise hangisinin feda edileceğine karar vermek zorunda kalır.
İlk Savunma Hattı: Low Memory Killer
Bellek kritik seviyelere yaklaştığında devreye giren ilk mekanizma Low Memory Killer (LMK)'dir. LMK, her process'e atanmış OOM Score (Out of Memory Score) değerini kullanarak hangisinin önce öldürüleceğini belirler.
OOM Score ne kadar yüksekse o process'in öldürülme olasılığı o kadar artar. Şu an ekranda aktif olan uygulama en düşük skora sahipken, boşta bekleyen ve uzun süredir dokunulmayan arka plan process'leri en yüksek skora sahiptir.
LMK bu sıralamayı sürekli günceller ve bellek baskısı arttıkça yukarıdan aşağıya doğru process'leri sonlandırır. Önce boş process'ler gider, ardından arka plan uygulamaları, ardından görünür ama odakta olmayan bileşenler. En son korunan her zaman kullanıcının aktif olarak etkileşimde bulunduğu uygulamadır.
Android 10 Sonrası: LMKD
Android 10 ile birlikte LMK mekanizması yeniden tasarlandı. Eski kernel düzeyi LMK'nın yerini LMKD (Low Memory Killer Daemon) adlı kullanıcı alanı servisi aldı.
LMKD, bellek baskısını çok daha ayrıntılı değerlendirir. Yalnızca anlık bellek miktarına bakmakla kalmaz, belleğin ne hızda tükendiğini de hesaba katar. Hızlı tükeniş tespit edildiğinde daha proaktif davranır ve kritik eşiğe ulaşmadan önce temizliğe başlar.
Bu değişiklik özellikle düşük RAM'li cihazlarda bellek yönetimini önemli ölçüde iyileştirdi.
onTrimMemory: Uygulamaya Erken Uyarı
LMK bir process'i öldürmeden önce Android, uygulamalara kendilerini temizlemeleri için bir fırsat sunar. Bu fırsat onTrimMemory callback'i aracılığıyla iletilir.
onTrimMemory, Activity ve Application sınıflarında override edilebilen bir metottur. Android bellek baskısı seviyesini bu callback aracılığıyla uygulamaya bildirir. Uygulama bu uyarıyı alınca önbelleğini boşaltabilir, gereksiz nesneleri serbest bırakabilir ve bellek kullanımını azaltabilir.
Bu callback farklı aciliyet seviyelerinde gelir. Arka planda olduğunuzu ve sistemin biraz belleğe ihtiyaç duyduğunu bildiren ılımlı uyarılar geldiğinde önbellek temizliği yapmak yeterlidir. Kritik seviye uyarısı geldiğinde ise elinizdeki her şeyi bırakmak gerekir çünkü process'inizin öldürülmesi an meselesidir.
zRAM: Mobil Dünyanın Swap Çözümü
Geleneksel swap Android için uygun olmasa da tamamen alternatifsiz değildir. Android, zRAM adlı bir mekanizma kullanır.
zRAM, RAM'in bir bölümünü sıkıştırılmış bellek alanı olarak ayırır. Aktif kullanılmayan bellek sayfaları sıkıştırılarak bu alana taşınır. Bu sayede fiziksel RAM kapasitesinin ötesinde veri tutmak mümkün hale gelir.
Geleneksel swap'tan farkı şudur: Veri diske değil, RAM'in kendisine yazılır. Sıkıştırma ve açma işlemleri disk erişiminden çok daha hızlıdır. Bu yaklaşım belirli durumlarda efektif bellek kapasitesini önemli ölçüde artırır.
OOM Killer: Son Çare
Her şey başarısız olursa — LMK yeterli belleği kurtaramadıysa, onTrimMemory callback'leri işe yaramadıysa — Linux çekirdeğinin kendi mekanizması devreye girer: OOM (Out of Memory) Killer.
OOM Killer, sistemi ayakta tutmak için en yüksek OOM Score'a sahip process'i hiçbir uyarı vermeden anında sonlandırır. Bu son çaredir ve normal koşullarda nadiren tetiklenir. Tetiklendiğinde ise sistem loglarında Killed process satırları görülür.
Geliştirici Perspektifinden Bakış
Bu mekanizmaları anlamak uygulamanızın bellek davranışını şekillendirmenize doğrudan katkı sağlar.
onTrimMemory callback'ini mutlaka implement edin. Bellek baskısı geldiğinde görsel önbelleğinizi, geçici verilerinizi ve yeniden oluşturulabilecek her şeyi serbest bırakın. Bu hem kullanıcı deneyimini korur hem de sisteme karşı iyi niyetin somut bir göstergesidir.
Uygulamanızın bellek tüketimini Android Studio Memory Profiler ile düzenli olarak izleyin. Özellikle uzun kullanım oturumlarında bellek kullanımının nasıl değiştiğini gözlemlemek, henüz kendini göstermemiş sorunları erkenden yakalamanızı sağlar.
Ve son olarak: Düşük RAM'li cihazlarda test yapmayı ihmal etmeyin. Geliştiricilerin çalıştığı güçlü cihazlarda fark edilmeyen bellek sorunları, kullanıcıların elindeki bütçe dostu cihazlarda kendini acımasızca gösterir.