Bellek kullanımını incelemeniz gerektiğinde, en önemli bellek kategorilerini belirlemek için üst düzey değerlendirme araçlarıyla başlayın.
dumpsys meminfo
Bir uygulamanın bellek kullanımına genel bakış elde etmenin en yaygın yolu dumpsys meminfo yöntemidir. Tüm bellek eşlemelerini içeren ayrıntılı bir döküm görmek için -a işaretini eklemek genellikle yararlı olur:
adb shell dumpsys meminfo -a <package_name_or_pid>
Aşağıda, bellek baskısı altındaki bir uygulamanın örnek çıkışı verilmiştir (yüksek SwapPss değerine dikkat edin):
** MEMINFO in pid 4562 [com.android.memorylab] **
Pss Private Private SwapPss Rss Heap Heap Heap
Total Dirty Clean Dirty Total Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------
Native Heap 394 268 64 17440 4264 29416 18128 8040
Dalvik Heap 165 8 0 672 8196 40949 32757 8192
Dalvik Other 47 28 0 604 1132
Stack 112 108 4 312 120
...
TOTAL 33197 580 788 21920 167776 70365 50885 16232
App Summary
Pss(KB) Rss(KB)
------ ------
Java Heap: 12 32608
Native Heap: 268 4264
Code: 724 125672
Stack: 108 120
Graphics: 0 0
Private Other: 256
System: 31829
Unknown: 5112
TOTAL PSS: 33197 TOTAL RSS: 167776 TOTAL SWAP PSS: 21920
Objects
Views: 15 ViewRootImpl: 1
AppContexts: 5 Activities: 1
...
Verileri yorumlama
- Pss Total: Orantılı küme boyutu. Bu,
Private Dirty + Private Cleanile işleminizin diğer işlemlerle (Zygote başlatma görüntüsü gibi) paylaşılan adil bellek payının toplamıdır. Bu, "bu uygulamanın sorumlu olduğu bellek miktarı" için en iyi metriktir. - Özel Kirli: Bu, yalnızca işleminizin kullandığı ve değiştirilmiş (veya anonim bellek olan) RAM'dir. Bu bellek bırakılamadığı için sızıntıları bulma konusunda en önemli sayıdır.
- Özel Temiz: Yalnızca işleminiz tarafından kullanılan ancak depolama alanındaki bir dosyanın (DEX dosyası gibi) değiştirilmemiş kopyası olan RAM. Bellek azsa işletim sistemi tarafından bırakılabilir.
SwapPss: Sıkıştırılmış ve ZRAM'e aktarılmış bellek. Bu durum, sistemde bellek baskısı olduğunda veya Android Çalışma Zamanı, sıkıştırılacak arka plan işlemleri (kullanılmayan veya etkin olmayan sayfalarını ZRAM'e taşıma) belirlediğinde ortaya çıkabilir.
dumpsysörneğinde,Native HeapveDalvik Heap'nin neredeyse tamamı ZRAM'e taşınmıştır.Önemli nokta: "Uygulama Özeti" bölümündeki Java Yığını ve Yerel Yığın değerleri, yerleşik (fiziksel) belleği temsil eder. Bir uygulamanın belleği ZRAM'e sıkıştırılmışsa bu özel özet değerleri beklenenden çok daha düşük görünebilir. Tam resmi görmek için her zaman TOTAL SWAP PSS veya ayrıntılı
SwapPsssütununu kontrol edin.Uygulama Özeti: Ayrıntılı satırları anlaşılır gruplar halinde birleştiren daha üst düzey bir kategorizasyon.
Nesneler: Sızdırılan
ActivitiesveViewRootImplörneklerini izlemek için kullanışlıdır. Uygulamanızdan çıkıp GC'yi zorlarsanızActivitiessayısı 0'a döner.
Bellek bütçesi bölümü
Android 18 ve sonraki sürümlerde dumpsys meminfo, tek bir uygulamayı döküme aldığında Bellek Bütçesi bölümünü de yazdırır. Bu bölüm, işlemin ve uygulamanın tamamının (paketin) memcg istatistiklerini okur. Bu sayede cgroup dosyalarını kendiniz bulmanız gerekmez. Allocate Java Memory (10MB) (Java Belleği Ayır (10 MB)) düğmesine üç kez dokunduktan sonra MemoryLab örnek uygulamasının ön plandaki bölümü şu şekilde görünür:
Memory Budget
Process(KB) Package(KB)
----------- -----------
Current Usage: 83820 87976
Limit: none 4718592
Limit Source: none MemoryLimiter
Peak Usage: 85136 89292
Swap Used: 0 0
Usage Breakdown
Anonymous: 81700 81700
File: 96 4200
File Mapped: 16 616
Shared Memory: 16 16
Kernel: 1580 1632
Page Tables: 640 640
Slab: 439 458
Pressure & Reclaim
Throttle Events: 0 0
Refaults (Anon): 0 0
Refaults (File): 0 0
- Mevcut Kullanım: Memcg'ye (
memory.current) yüklenen bellek. Bu, bellek bütçelerinin sınırladığı sayıdır. Örnekte, üç adet 10 MB Java tahsisinden sonra yaklaşık 36.700 KB artarak TOTAL PSS ile uyumlu hale geldi. Daha önceki bir çalıştırmadan kalan önbelleğe alınmış dosya sayfaları henüz geri alınmadığında, tek işlemli bir uygulama için bile paket toplamı işlem toplamından daha yüksek olur. - Sınır: Şu anda geçerli olan geri alma eşiği (
memory.high) veya eşik yoksanone. Örnekte, paketin sistem belleği sınırı var ve işlemin kendi sınırı yok. - Sınır Kaynağı: Sınırın nereden geldiği.
AndroidManifest, uygulama manifestinde beyan edilen bir<memory-budget>,MemoryBudgetManager, uygulamanın çalışma zamanında ayarladığı bir bütçe,MemoryLimiter, sistem bellek sınırı veam memory-limiter,adbile ayarlanan manuel geçersiz kılmadır. - En Yüksek Kullanım: memcg oluşturulduğundan beri en yüksek ücret (
memory.peak). Bu, desteklemeyen çekirdeklerdeN/Adeğerini gösterir. - Kullanılan Swap: ZRAM'e sıkıştırılmış bellek (
memory.swap.current). - Kullanım dökümü: Anonim ve dosya destekli bellek gibi
memory.statana alanları. - Baskı ve Geri Kazanma: Kısıtlama Etkinlikleri, memcg'nin
memory.highsınırını kaç kez aştığını sayar. Refaults, takas edilen veya çıkarılan ve daha sonra tekrar ihtiyaç duyulan sayfaları sayar. Uygulamayı kullanırken bu sayılar artıyorsa sınır, uygulamanın çalışma grubundan daha dardır.
-a veya -v işaretiyle bu bölümde memory.stat ve memory.events'deki her ham sayaç da listelenir.
Uygulama alıştırması: meminfo ile hızlı önceliklendirme
Bu alıştırmada, farklı tahsis türlerinin meminfo içinde nasıl gösterildiği açıklanmaktadır.
Uygulamayı başlatma:
adb shell am start -W -n com.android.memorylab/.MainActivityReferans bellek kullanımını kontrol etme:
adb shell dumpsys meminfo -s com.android.memorylab(
-sişareti, bellek kategorilerinin kısa ve öz bir özetini sağlar).Java Belleği Ayırma: Uygulamada Java Belleği Ayır (10 MB) düğmesine 3 kez dokunun.
Değişikliği gözlemleyin:
meminfo -skomutunu tekrar çalıştırın. Java Yığın değerinin yaklaşık 30.000 KB (30 MB) arttığını görürsünüz.Yerel Bellek Ayırma: Yerel Bellek Ayır (1 GB Sıkıştırılamaz) düğmesine bir kez dokunun.
Değişikliği gözlemleyin:
meminfo -skomutunu tekrar çalıştırın. Yerel Yığın değeri artık büyük bir artış (~1.000.000 KB) göstermelidir.memcg ile karşılaştırma (Android 18 ve sonraki sürümler):
meminfo -sçıkışının sonundaki Bellek Bütçesi bölümüne bakın. Hem Java hem de yerel ayırmalar uygulamanın memcg'sine yüklendiğinden, her ayırmadan sonra TOTAL PSS ile birlikte Current Usage da artar.
Genel görünüm
Sistem genelinde bellek kullanımını görmek için şu komutu çalıştırın:
adb shell dumpsys meminfo
Bu komut; toplam RAM, boş RAM ve PSS'ye göre sıralanmış işlemlerin listesi dahil olmak üzere RAM kullanımının özetini gösterir.
Temel sistem metrikleri
- ZRAM: RAM'deki sıkıştırılmış takas.
- DMA-BUF: Grafikler ve paylaşılan bellek arabellekleri. Modern Android sürümleri, kullanıcı arayüzü oluşturma için DMA-BUF'u yoğun bir şekilde kullanır.
DMA-BUFtoplamı çok yüksekse/sys/kernel/debug/dma_buf/bufinfokullanarak grafik ağırlıklı işlemleri inceleyin. - Kayıp RAM: Çekirdek veya herhangi bir işlem tarafından hesaba katılmayan bellek (ör. donanıma ayrılmış bölgeler).
memcg istatistikleri
Her uygulama işleminin kendi bellek kontrol grubu (memcg) vardır ve çekirdek, bu gruba yüklenen belleğin toplamını tutar (bu hesaplamanın RSS ve PSS'den nasıl farklı olduğunu öğrenmek için memcg bölümüne bakın). Bu dosyaları okumak kolaydır ve uygulamanızı rahatsız etmez. Bu nedenle, kullanıcı işlemleri akışını çalıştırırken her saniye örnekleyebilirsiniz.
Cgroup düzeni cihazlar arasında farklılık gösterebileceğinden, yolu kendiniz oluşturmak yerine /proc/<PID>/cgroup dosyasının 0:: satırından bir işlemin memcg yolunu bulun. Cihaz kabuğunun tırnak işaretlerini görmesi için her cihaz komutunu adb shell'ya tek tırnak içine alınmış dize olarak iletin:
PID=$(adb shell pidof -s <package_name>)
CG=/sys/fs/cgroup$(adb shell "sed -n 's/^0:://p' /proc/$PID/cgroup")
adb shell "cat $CG/memory.current $CG/memory.swap.current"
adb shell "grep -E '^(anon|file|workingset_refault_.*) ' $CG/memory.stat"
Önemli dosyalar şunlardır:
memory.current: İşleme ayrılan bellek (bayt cinsinden). Bellek bütçelerinin sınırladığı sayı budur.memory.swap.current: ZRAM'e sıkıştırılmış bellek (bayt cinsinden).memory.stat: Ücretin dökümü (boyutlar bayt cinsinden gösterilir).anon, Java ve yerel yığınlar gibi anonim bellektir.file, kod ve kaynaklar gibi dosya destekli sayfa önbelleğidir.workingset_refault_anonveworkingset_refault_file, takas edilen veya çıkarılan ve daha sonra tekrar ihtiyaç duyulan sayfaları sayar. Yeniden hata sayılarının artması, işlemin belleğinin yetersiz olduğu anlamına gelir.memory.events: Bellek sınırı etkinliklerinin sayısı.high, işleminmemory.highsınırını aştığı için kaç kez kısıtlandığını sayar.
İşlem memcg'sinin ana dizini, uygulamanın tamamına (UID'sine) aittir. Dosyaları, uygulamanın çalışan tüm işlemlerinin belleğini ve uygulamanın çıkış yapmış ve henüz geri alınmamış önceki işlemlerinden kalan önbelleğe alınmış dosya sayfalarını içerir:
adb shell "cat $CG/../memory.current"
İzin hatası alırsanız adb root komutunu çalıştırıp tekrar deneyin. Bazı cihazlar bu dosyaları yalnızca root olarak okumanıza izin verir.
MemoryLab örnek uygulamasıyla bu dosyaların rehberli bir açıklaması için Uygulamalı alıştırma: memcg'yi keşfetme başlıklı makaleyi inceleyin.
showmap
Bir işlemin bellek eşlemelerinin çok daha ayrıntılı dökümü için showmap komutunu kullanın. Bu araç, /proc/<pid>/smaps kaynağından okuma yapar.
adb shell showmap <pid>
showmap, işlemdeki her bellek eşlemesini listeler. Aranacak önemli eşlemeler şunlardır:
[anon:scudo:primary]veya[anon:libc_malloc]: Yerel yığın. Modern Android sürümleri Scudo ayırıcıyı kullanır.*.art: Java yığın görüntüleri (ör. başlatma görüntüsü).[anon:dalvik-main space]: Ana Java yığını.*.so: Paylaşılan kitaplıklar.*.{oat,dex,odex,vdex}: Derlenmiş DEX kodu.
En büyük özel bellek tüketicilerini bulmak için çıkışı sıralayabilirsiniz:
# Sort by private clean + private dirty memory
adb shell showmap <pid> | awk '{print $6+$7, $0}' | sort -rn | head -n 10
Örnek çıkış:
virtual shared shared private private Anon Shmem File Shared Private
size RSS PSS clean dirty clean dirty swap swapPSS HugePages PmdMapped PmdMapped Hugetlb Hugetlb Locked # object
-------- -------- -------- -------- -------- -------- -------- -------- -------- --------- --------- --------- -------- -------- -------- ---- ------------------------------
2776 18176 5784 2823 0 3008 308 2468 4700 4700 0 0 0 0 0 0 47 [anon:scudo:primary]
560 952 876 657 316 0 560 0 12 12 0 0 0 0 0 0 8 /data/app/.../base.apk
448 393216 448 448 0 0 0 448 0 0 0 0 0 0 0 0 2 [anon:dalvik-main space]
...
Uygulama alıştırması: showmap ile ayrıntılı inceleme
Belirli bellek eşlemelerini nasıl tanımlayacağınızı ve temiz ile kirli bellek arasındaki farkı nasıl ayırt edeceğinizi öğrenin.
- Mmap Temiz Bellek: MemoryLab uygulamasında Mmap Temiz Anonim Bellek (10 MB) düğmesine bir kez dokunun.
İşlem kimliğini alma: Uygulamanın kullanıcı arayüzünde işlem kimliği gösterilir. Bu komutla da bulabilirsiniz:
adb shell pidof com.android.memorylabShowmap ile inceleme:
# Replace <PID> with the actual process ID from the previous step adb shell showmap <PID> | grep "memorylab-clean"Eşlemeyi tanımlayın: Tam olarak 10.240 KB sanal boyuta sahip
[anon:memorylab-clean]etiketli anonim bir eşleme görürsünüz. Bu eşlemenin özel kirli değerinin büyük olasılıkla 0 olduğunu unutmayın. Sanal alanı ayırmak içinmmapkullandığımız ancak henüz bu alana yazmadığımız için bu, "temiz" anonim bellektir (bu nedenle fiziksel RAM tüketilmez).Yerel Yığın Karşılaştırması: Bunu,
meminfoalıştırmasının 5. adımından sonra çalıştırdığınızdashowmapiçinde görünecek olan[anon:scudo:primary]eşlemeleriyle karşılaştırın. Bu 1 GB'lık yerel ayırma aslında her sayfaya yazdığı için bu sayfalar "kirli"dir ve özel kirli sütununda yoğun bir şekilde görünür.Uzman ipucu (Büyük Nesneler):
meminfoalıştırmasındaki Java Yığını ayırmalarına dikkat edin. 10 MB'lık bayt dizileri oldukları içinshowmapiçinde[anon:dalvik-free list large object space]olarak görünebilirler. Android Çalışma Zamanı (ART), ana yığında parçalanmayı önlemek için 12 KB'tan büyük nesneleri ayrı bir Büyük Nesne Alanı'na (LOS) yerleştirir.
procstats
meminfo, belirli bir zamandaki durumu gösterirken procstats, çalışan tüm uygulamaların durumunu ve bellek kullanımını düzenli olarak örnekleyerek geçmiş verileri sağlar. Bu, uzun süreli bellek sağlığını izlemek için kullanılan birincil araçtır ve Android ayarlarındaki bellek kullanımı raporlamasını yönlendirir.
# View stats for the last 3 hours
adb shell dumpsys procstats --hours 3
Durumları anlama
procstats çıktısı çok fazla olabilir. En önemli kısım, her işlem durumunun
yanındaki parantez içindeki metriklerdir:
Top: 100% (54MB-64MB-67MB / 49MB-58MB-61MB / 110MB-120MB-130MB over 4)
Biçim şu şekildedir: (% time in state) (minPss-avgPss-maxPss / minUss-avgUss-maxUss / minRss-avgRss-maxRss over samples)
- Pss (Orantılı Küme Boyutu): Paylaşılan bellek, işlemler arasında orantılı olarak bölünür.
- Uss (Unique Set Size): Yalnızca bu işlem tarafından kullanılan bellek (Private Clean + Private Dirty'ye eşdeğer).
- Rss (Yerleşik Küme Boyutu): Tüm paylaşılan sayfalar dahil olmak üzere kullanılan toplam fiziksel bellek (fazla sayma eğilimindedir).
Bu neden önemli?
- Kararlı uygulama: Minimum, ortalama ve maksimum değerler birbirine yakındır.
- Bellek Sızıntısı: Maksimum değer, minimum değerden önemli ölçüde yüksektir ve örnek sayısı arttıkça ortalama değer zaman içinde yükselir.
- Dalgalı Kullanım: Maksimum değer, ortalama değerden çok daha yüksektir. Bu durum, yanlış zamanda gerçekleşirse OOM'lere neden olabilecek geçici ağır işlemleri (ör. görüntü işleme) gösterir.
İşlem durumları
procstats, uygulamaları çeşitli durumlarda (genellikle kısaltılmış olarak) izler:
- Kalıcı: Her zaman çalışan kritik sistem işlemleri.
- Üst: Uygulama şu anda ön plandadır ve kullanıcı tarafından görülebilir.
- ImpFg (Önemli Ön Plan): Kritik arka plan işlemleri (ör. IME'ler) veya ön plan hizmeti olan uygulamalar.
- ImpBg (Önemli Arka Plan): Sistem için önemli olduğu düşünülen arka plan işlemleri.
- Fgs / BFgs: Ön plan hizmetleri veya bağlı ön plan hizmetleri.
- Service / ServRst: Arka plan hizmetleri veya şu anda yeniden başlatılan hizmetler.
- Önbelleğe alınmış / LastAct: Hızlı yeniden başlatma için arka planda önbelleğe alınan uygulamalar. Sistemin bunları sonlandırması güvenlidir.
Cihaz bellek durumu ve çalışma süresi istatistikleri
procstats, cihazın tamamının bellek baskısı altında ne kadar süre kaldığını da izler. Çalışma süresi istatistikleri bölümünü bulun:
Run time Stats:
SOff/Norm: +1h10m15s
SOn/Norm: +15m20s
Low: +2m10s
Crit: +45s
- SOff / SOn: Ekran kapalı ve ekran açık.
- Norm / Mod / Low / Crit: Bellek baskısı seviyeleri (Normal, Orta, Düşük, Kritik).
Bir cihaz Düşük veya Kritik durumlarda önemli ölçüde zaman harcıyorsa çekirdek, belleği agresif bir şekilde geri aldığından ve Low Memory Killer (LMK) arka plan işlemlerini sonlandırmaya başladığından cihaz yavaş çalışır. Ardından, cihaz bu stresli durumlardayken özellikle hangi uygulamaların yüksek bellek kullanımına sahip olduğunu görmek için paket başına istatistikleri inceleyebilirsiniz.
← Kavramlar | ↑ Yukarı | Java →