Android'de bellek kullanımını anlamak için sisteme üst düzey Java nesnelerinden alt düzey çekirdek sayfalarına kadar çeşitli farklı açılardan bakmanız gerekir.
Performans uçurumu
Bellek kullanımı kendi başına iyi veya kötü bir şey değildir. Önemli olan, belleği ne için kullandığınızdır. Ancak cihazda kullanılabilir bellek sınırına yaklaştıkça "performans uçurumundan düşersiniz".

Uçurumdan uzaktayken az miktarda bellek kullanımı eklemenin (ör. 50 MB) performans üzerinde fark edilebilir bir etkisi olmayabilir. Ancak kullanılabilir RAM tükendiğinde bir uçuruma ulaşılır. Bu noktada işletim sistemi, yer açmak için belleği sayfalara ayırmaya ve işlemleri sonlandırmaya başlar. Bu eşikten sonra, bellek kullanımındaki küçük bir artış bile ciddi "thrashing" sorunlarına yol açabilir. Bu durumda, kritik işlemler sonlandırıldığı için cihaz yanıt vermez hale gelebilir veya yeniden başlatılıyor gibi görünebilir.
Android yığını
Android yığınının her katmanının kendine özgü bir bellek görünümü vardır:

- Uygulamalar (Java/Kotlin): Geliştiriciler öncelikle Java yığınında ayrılan Java nesnelerini görür.
- Android Çalışma Zamanı (ART): ART, çekirdekten gelen sanal bellek sayfalarını kullanarak Java/Kotlin yığınını yönetir. Eski adıyla Dalvik (terimler bazen birbirinin yerine kullanılır).
- Linux Çekirdeği: Çekirdek, belleği fiziksel ve sanal sayfalar olarak görür. Geleneksel olarak bu sayfalar 4 KB boyutundadır ancak Android, 16 KB sayfa boyutlarını da destekler. Çekirdek, "Java nesneleri" hakkında hiçbir şey bilmez.
Belleği optimize etmek istiyorsanız kendi katmanınızda optimizasyon yapmanız (ör. daha az bit eşlem yükleme) veya üst düzey ayırmalarınızın fiziksel sayfa kullanımına nasıl dönüştüğünü görmek için altınızdaki katmanları anlamanız gerekir.
Bellek türleri: anonim ve dosya destekli
İşletim sisteminin belleği nasıl geri aldığını incelemeden önce Linux'taki bellek sayfalarının iki temel kategorisini anlamanız gerekir:
- Anonim Bellek (
anon): Depolama alanındaki bir dosya tarafından desteklenmeyen bellek. C/C++malloc(Scudo ayırıcı gibi) tarafından ayrılan bellek ve Java/Kotlin yığınındaki Java nesneleri için ayrılan bellek buna dahildir. Bu belleğin geri döneceği bir kaynak dosyası olmadığından işletim sistemi, bu belleği RAM'de tutmalı veya baskı altındayken sıkıştırıp ZRAM'e aktarmalıdır. - Dosya Destekli Bellek (
file): Doğrudan depolama alanındaki bir dosyadan eşlenen bellek. Yürütülebilir kod (DEX dosyaları,.soyerel kitaplıklar) ve yazı tipleri de buna dahildir.
Bellek eşlemeli dosyalar (mmap)
Android, hem dosya destekli hem de anonim belleği bir işlemin adres alanıyla eşlemek için mmap kullanır.
Dosya destekli bellek söz konusu olduğunda sayfalar şu şekilde sınıflandırılır:
- Temiz bellek: Değiştirilmemiş bir dosyadan eşlenen sayfalar. Sistemin daha fazla belleğe ihtiyacı olursa çekirdek, daha sonra doğrudan depolama alanındaki dosyadan yeniden yüklenebilecekleri için bu sayfaları bırakabilir.
- Kirli Bellek: İşlem tarafından değiştirilen sayfalar. Bunlar silinemez. Anonim bellek gibi davranırlar ve RAM'de tutulmaları veya ZRAM'e taşınmaları gerekir.
Android, bellek eşlemeye uygun dosya biçimlerini (ör. DEX) tercih eder. Bu sayede sistem, baskı altındayken temiz belleği kolayca geri kazanabilir. Anonim ve kirli bellek kolayca bırakılamadığından, yüksek özel kirli/anonim bellek, sistemin aşırı yüklenmesinin ve düşük bellek sonlandırıcı (LMK) müdahalelerinin birincil nedenidir. Uygulamanız çok fazla özel kirli bellek kullanıyorsa performans düşüşüne doğrudan katkıda bulunuyorsunuz demektir.
Zygote işlem modeli
Android, Zygote adlı bir işlem kullanarak yeni uygulamaları başlatma maliyetini en aza indirir.
- Zygote, başlatma sırasında başlar ve yaygın çerçeve sınıfları ile kaynakları belleğine önceden yükler. Çekirdek açısından bu, anonim kirli bellek haline gelir ancak Zygote işlemine özgüdür.
- Yeni bir uygulama başlatıldığında sistem, Zygote işlemini çatallar.
- Yeni alt işlem, yazma üzerine kopyalama (COW) semantiğiyle paylaşılan eşlemeyi kullanarak Zygote'un belleğini devralır.

Alt işlem yalnızca Zygote'tan devralınan belleği okuduğu sürece fiziksel bellek sayfaları tüm işlemler arasında paylaşılmaya devam eder. Bir alt işlem, paylaşılan bir sayfayı değiştirdiğinde çekirdek, işlem için o sayfanın özel bir kopyasını şeffaf bir şekilde oluşturur. Bu model, birçok işlemin belleklerinin büyük bir kısmını (özellikle çerçeve kodu ve kaynakları) paylaşmasına olanak tanıyarak sistemin bellekte kapladığı toplam alanı önemli ölçüde azaltır.
RSS, PSS, USS ve memcg
Bellek, işlemler arasında yoğun bir şekilde paylaşıldığı için (çoğunlukla Zygote modeli aracılığıyla) bir işlemin bellek kullanımını hesaplamanın birkaç yolu vardır. RSS, PSS ve USS, bir işlemin adres alanına eşlenen sayfaları sayar:

- RSS (Yerleşik Küme Boyutu): İşlemin RAM'de sahip olduğu toplam sayfa sayısı. Bu, paylaşılan sayfaları birden çok kez saydığı için (paylaşan her işlem için bir kez) kullanımı olduğundan fazla gösterir.
- PSS (Orantılı Küme Boyutu): İşleme özgü toplam bellek miktarı ve paylaşılan bellekteki orantılı payı. Bir sayfa 5 işlem tarafından paylaşılıyorsa her işlem, bu sayfanın 1/5'i için ücretlendirilir.
- USS (Benzersiz Küme Boyutu): İşleme özgü bellek miktarı. İşlem sonlandırılırsa sisteme döndürülecek bellek miktarıdır.
memcg: çekirdeğin kendi kaydı
Çekirdek, her işlemin kullandığı belleğin kendi çalışan toplamını da tutar. Bu bellek eşlenmiş olsun veya olmasın. Android'de her uygulama işlemi, tüm uygulama için bir memcg içinde iç içe yerleştirilmiş kendi bellek kontrol grubuna (memcg) aittir (Android memcg hiyerarşisi bölümüne bakın).
Bir bellek sayfası tahsis edildiğinde çekirdek, bu sayfayı tahsis eden işlemin memcg'sine ücretlendirir. Toplam ücret, memcg'nin memory.current dosyasında yer alır.
memcg hesaplaması; RSS, PSS ve USS'den birkaç önemli açıdan farklıdır:
- Her sayfa tam olarak bir kez ücretlendirilir. Bu ücret, sayfayı belleğe ilk getiren işlemin memcg'sine yansıtılır. Diğer işlemler daha sonra aynı sayfayı eşlese bile ücret orada kalır. Zygote'un önceden yüklediği sayfalar uygulamanıza değil, Zygote'a ücretlendirilir. Uygulamanız bu sayfalardan birine yazdığında özel kopya uygulamanıza ücretlendirilir.
- Sayfa tablosu metriklerinin göremediği bellekleri içerir.
memory.currentuygulamanızın eşleme yapmadan okuduğu dosya sayfalarını sayar (örneğin,readveyapreadile okunan veritabanı sayfaları). - Takas işlemlerini ayrı olarak izler. ZRAM'e sıkıştırılan bellek
memory.currentalanındanmemory.swap.currentalanına taşınır. Böylece her ikisini de tahmin etmeden görebilirsiniz. - Okuma maliyeti düşüktür. Sayaçlar her zaman günceldir ve okunmaları, uygulamanızın adres alanını kilitlemez veya taramaz.
- Sistem tarafından belirlenen sınırdır. Android'in uygulamalara uyguladığı bellek sınırları ve bellek bütçeleri, memcg ücreti üzerinden işlem yapar.
Donanım bit eşlemlerinin arkasındaki arabellekler gibi ekran kartı belleği genellikle uygulamanızın memcg'sine yüklenmez.
Hangi metrikler ne zaman kullanılır?
Doğru bellek metriğini seçmek, neyi ölçmeye çalıştığınıza ve ölçtüğünüz ortama bağlıdır. Android 17 QPR2 (API düzeyi 37.2) ve sonraki sürümleri çalıştıran cihazlarda kendi uygulamanızı izlerken memcg ile başlayın.
| Metrik | En Uygun Olduğu Durumlar | Anahtar Gücü | Ana dezavantaj |
|---|---|---|---|
| memcg | Belirli bir uygulamayı zaman içinde takip etme ve bütçelerle karşılaştırma | Her sayfayı bir kez sayar, eşlenmemiş sayfa önbelleğini içerir, takas alanını ayrı olarak izler. Okuma maliyeti düşüktür. | Android 17 QPR2'den önceki sürümlerde tüm cihazlarda kullanılamaz. Paylaşılan sayfalar, onlara ilk dokunan işlemden ücretlendirilir. |
| PSS | Sistem genelinde bellek anlık görüntüleri | Paylaşılan belleği doğru şekilde oranlar. PSS'nin toplamı, kullanılan toplam belleğe eşittir. | Çalışan diğer işlemlere göre dalgalanır. Belirli bir uygulamayı zaman içinde karşılaştırmak için uygun değildir. |
| RSS | Belirli bir uygulamayı zaman içinde izleme, saha telemetrisi | Diğer işlemlerden bağımsız olarak kararlıdır. Hızlı ve ucuz bir şekilde toplanabilir. | Paylaşılan belleği birden fazla kez saydığı için toplam kullanımı olduğundan fazla gösterir. |
| USS | Bir işlemi sonlandırmanın etkisini değerlendirme | Uygulama sonlandırılırsa tam olarak ne kadar bellek boşaltılacağını gösterir. | Paylaşılan belleği tamamen yoksayar. |
memcg (bellek kontrol grubu ücreti)
- En uygun kullanım alanı: Android 17 QPR2 veya sonraki sürümleri çalıştıran cihazlarda, tek bir uygulamanın zaman içindeki, kritik kullanıcı yolculuklarındaki (CUJ) veya uygulama sürümleri arasındaki bellek kullanımını izleme. Ayrıca, bellek bütçelerini kalibre ederken izlemeniz gereken metrik de budur. Çünkü bütçelerin sınırladığı sayı budur.
- Neden: RSS gibi memcg ücreti de diğer uygulamalar uygulamanızla sayfa paylaşmaya başladığında veya paylaşmayı durdurduğunda değişmez. RSS'den farklı olarak, bir sayfayı hiçbir zaman iki kez saymaz. Bu sayede, uygulamanızın çalışan tüm işlemlerinin ücretini toplayabilirsiniz. Uygulama genelindeki memcg, bu toplamdan daha yüksek olabilir. Bunun nedeni, çekirdek tarafından geri alınana kadar çıkış yapılan işlemlerden önbelleğe alınmış dosya sayfalarını saklamasıdır. Ayrıca, RSS, PSS ve USS'nin kaçırdığı bellekleri (ör. eşlenmemiş dosya önbelleği) de sayar. Çekirdek, sayfaları şarj ederken sayaçları güncellediği için okumak ucuzdur.
- Nasıl okunur: Bir işlemin memcg dizininde
memory.current,memory.swap.currentvememory.statdeğerlerini okuyun (memcg istatistikleri bölümüne bakın). Android 18 ve sonraki sürümlerdedumpsys meminfobunları da yazdırır. Uygulamanızın içindenMemoryBudgetManageryöntemini kullanın. - Saha Ölçümüyle İlgili En İyi Uygulamalar: RSS bölümünde açıklanan nedenlerle anonim bellek + takas'ı izleyin:
memory.statvememory.swap.current'ninanonalanı.memory.statalanınınfilealanı, uygulamanızın bir kez okuduğu ve çekirdeğin henüz geri almadığı dosya sayfalarını içerir. Bu nedenle, uygulamanız bu belleği kullanmayı bıraktıktan sonramemory.currentbir süre yüksek kalabilir. - Dikkatli olunması gereken durumlar: Sayfalar, ilk dokunan işleme göre ücretlendirildiğinden uygulamanız, diğer işlemlerden önce okuduğu paylaşılan dosya sayfaları (ör. yazı tipi veya paylaşılan kitaplık) için ücretlendirilir.
Bunun tersine, uygulamanızın da kullandığı sayfalar için başka bir işlemden ücret alınabilir. Dosya destekli bellek için cihazlar ve çalıştırmalar arasında küçük farklılıklar olabilir. Karşılaştırma yaparken
anonve takas alanını kullanın.
PSS (Orantılı Küme Boyutu)
- En uygun kullanım alanı: Belirli bir cihazın belirli bir zamandaki sistem belleğinin tam anlık görüntüsünü alma.
- Neden: PSS, çalışan tüm işlemler için PSS toplamının sistemdeki işlemler tarafından kullanılan toplam belleğe eşit olduğu kullanışlı bir matematiksel özelliğe sahiptir. Paylaşılan belleği mükerrer sayım olmadan mükemmel bir şekilde paylaştırır.
- Ne zaman kullanılmamalıdır? Belirli bir işlemi iki farklı anlık görüntüde, farklı zamanlarda veya farklı cihazlarda karşılaştırmak için PSS'yi kullanmamalısınız. PSS, şu anda işleminizle sayfa paylaşan diğer işlemlerin sayısına bağlı olduğundan, uygulamanızın gerçek davranışı tamamen değişmeden kalsa bile uygulamanızın PSS'si dalgalanabilir.
RSS (Yerleşik Küme Boyutu)
- En uygun kullanım alanı: Tek bir uygulamanın zaman içindeki bellek kullanımını farklı kritik kullanıcı yolculuklarında (CUJ) izleme veya uygulama sürümleri arasında karşılaştırma yapma. Ayrıca saha telemetrisi için en pratik seçenektir.
- Nedeni: RSS, PSS'den daha kararlıdır. Diğer uygulamaların ne yaptığına bakılmaksızın işleminizle eşlenen bellek hakkında bilgi verir. Ayrıca RSS'yi toplamak maliyetli değildir. PSS veya USS'yi ölçmek için karmaşık çekirdek bellek yönetimi yapılarının taranması ve kilitlerin alınması gerekir. Bu işlemler çok sık yapılırsa sistem performans sorunlarına (ör. kullanıcı arayüzü takılması) neden olabilir.
- Saha Ölçümüyle İlgili En İyi Uygulamalar: Kullanımdaki cihazlardan veri toplarken genellikle anonim RSS + takas (ZRAM) ölçümü yapmak en iyisidir.
- Neden yalnızca anonim? Dosya destekli sayfalar (kod, uygulama kaynakları, yazı tipleri veya diğer bellek eşlemeli dosyalar gibi), sistem genelindeki sayfa önbelleği baskısı nedeniyle çekirdek tarafından herhangi bir zamanda çıkarılabilir. Belirli bir uygulamayı izlemek için dosya sayfalarını metriklere dahil etmek, işletim sisteminin bellek yönetimi kararlarından kaynaklanan gürültüye neden olur. Bu kararlar, diğer uygulamalardan veya sistemden kaynaklanan bellek baskısından etkilenebilir. Buna karşılık, anonim bellek (ör. Java ve yerel yığınlar) doğrudan uygulamanız tarafından kontrol edilir.
- Neden takas alanı eklenir? Bellek baskısı altında işletim sistemi, anonim sayfaları sıkıştırır ve ZRAM'e (takas) taşır. Yalnızca yerleşik anonim belleği ölçerseniz metrikleriniz, sistem baskı altında olduğu ve sayfalarınızı takas ettiği için bellek kullanımında yanlış bir "azalma" gösterebilir. Takas edilen bellek eklemek, uygulamanızın tahsis ettiği tüm anonim belleği (şu anda RAM'de veya ZRAM'de bulunup bulunmadığına bakılmaksızın) hesaba katmanızı sağlar.
- Mümkün olduğunda memcg'yi tercih edin. Android 17 QPR2 ve sonraki sürümleri çalıştıran cihazlarda,
memory.statiçindekianonvememory.swap.current, Zygote ile paylaşılan anonim sayfaları hariç tutan ve toplanması daha ucuz olan benzer bir ölçüm sağlar (memcg bölümüne bakın).
USS (Benzersiz Setteki Ürün Adedi)
- En uygun kullanım alanı: Bir işlemi sonlandırmanın sistem üzerindeki anlık etkisini belirleme.
- Neden: USS, işlem sonlandırıldığında (örneğin, Low Memory Killer arka plan programı
lmkdtarafından) hemen geri alınacak ve sisteme iade edilecek tam bellek miktarını doğru bir şekilde gösterir. - Kullanım şekli: Bu metrik, kalıcı işlemleri veya arka plan hizmetlerini değerlendirirken çok değerlidir. Arka plan işleminin sistem genelindeki maliyetini değerlendiriyorsanız USS, sistemin yalnızca bu işlemi canlı tutmak için ne kadar bellek harcadığını tam olarak gösterir.