Android'de mevcut bellek kullanımı nasıl elde edilir?


108

/ Proc / meminfo kullandım ve komut yanıtını çözümledim. Ancak sonuç şunu gösteriyor:

Mem Toplamı: 94348 kB Mem Serbest: 5784 kB

anlamına geliyor. sadece 5MB boş hafıza olduğunu gösterir. Android mobil ile mümkün mü? Cep telefonumda sadece 5-6 uygulama kurulu ve başka bir görev çalışmıyor. ancak yine de bu komut, çok az boş hafıza olduğunu gösterir.

Biri bunu açıklayabilir mi? veya android'de bellek kullanımını almanın başka bir yolu var mı?


2
Cihaz başına veya uygulama başına boş bellek mi görmeye çalışıyorsunuz? Uygulama başına ise, yığın a-la üzerinde hesaplanması gerekir Debug.getNativeHeapFreeSize().
IgorGanapolsky

1
/ Proc / meminfo kullanarak boş belleği (RAM'de) hesaplamak için MemFree , Buffers , Cached ve SwapCached toplamını almanız gerekir . Bu amaçla Android tarafından sağlanan API 16 ve servislerde çalışan bir API vardır. Meminfo, eski API'leri hedefliyorsanız yararlıdır.
AB

Yanıtlar:


174

DİKKAT: Bu yanıt, CİHAZ'ın bellek kullanımını / kullanılabilirliğini ölçer. Bu, uygulamanız için mevcut olan DEĞİLDİR. Uygulamanızın ne yaptığını ve yapmaya İZİN VERİLDİĞİNİ ölçmek için android geliştiricisinin yanıtını kullanın .


Android dokümanlar - ActivityManager.MemoryInfo

  1. parse / proc / meminfo komutu. Referans kodunu burada bulabilirsiniz: Android'de Bellek Kullanımını Alın

  2. aşağıdaki kodu kullanın ve mevcut RAM'i alın:

    MemoryInfo mi = new MemoryInfo();
    ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    activityManager.getMemoryInfo(mi);
    double availableMegs = mi.availMem / 0x100000L;
    
    //Percentage can be calculated for API 16+
    double percentAvail = mi.availMem / (double)mi.totalMem * 100.0;

0x100000L sayısının açıklaması

1024 bytes      == 1 Kibibyte 
1024 Kibibyte   == 1 Mebibyte

1024 * 1024     == 1048576
1048576         == 0x100000

Sayının bayttan mebibayta dönüştürmek için kullanıldığı oldukça açık

Not: Toplam belleği yalnızca bir kez hesaplamamız gerekir. bu nedenle, çağrı noktası 1'i kodunuzda yalnızca bir kez ve daha sonra, nokta 2'nin kodunu tekrar tekrar çağırabilirsiniz.


Hafıza boyutunu kontrol etmek istiyorum. MemoryInfo nedir?
Piraba

PIraba, Android API sınıfı. Burada developer.android.com/reference/android/app/… kontrol edin .
Badal

@SanjayJoshi Bunun nedeni, availMem değişkeninin belleği bayt cinsinden içermesidir. 1024 Bayt 1 KiloByte'a ve 1024 kilobayt 1 MegaByte'a eşittir. Yani 1024 * 1024 eşittir 1048576
Rolf ツ

2
Çifte dönüştür, yoksa yüzde Geçerli 0 olacak
blueether

1
@Rolf ツ üzgünüm ama 1024 bayt bir Kibibayt'a eşittir ve 1024 Kibibayt bir MibiByte'dır. Kilo ve Mega ondalık öneklerdir. 1000 bayt = 1 Kilobayt. Bu da cevapta yanlış açıklanmıştır.
JacksOnF1re

88

Hangi bellek sorgusunu almak istediğinizi tanımınıza bağlıdır.


Genellikle, yığın belleğinin durumunu bilmek istersiniz, çünkü çok fazla bellek kullanırsa, OOM alır ve uygulamayı kilitlersiniz.

Bunun için aşağıdaki değerleri kontrol edebilirsiniz:

final Runtime runtime = Runtime.getRuntime();
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

"UsedMemInMB" değişkeni "maxHeapSizeInMB" değerine availHeapSizeInMBne kadar yaklaşırsa , sıfıra o kadar yaklaşır, OOM elde edersiniz. (Bellek parçalanması nedeniyle, bu sıfıra ulaşmadan ÖNCE OOM alabilirsiniz.)

Bellek kullanımının DDMS aracının gösterdiği de budur.


Alternatif olarak, tüm sistemin ne kadar kullandığı gerçek RAM kullanımı vardır - bunu hesaplamak için kabul edilen cevaba bakın .


Güncelleme: Android O, uygulamanıza yerel RAM'i de kullandığından (en azından Bitmaps depolaması için, bu genellikle büyük bellek kullanımının ana nedenidir) ve yalnızca yığın değil, işler değişti ve daha az OOM elde edersiniz (çünkü heap artık bit eşlemler içermiyor, burayı kontrol edin ), ancak bellek sızıntılarınız olduğundan şüpheleniyorsanız bellek kullanımına yine de dikkat etmelisiniz. Android O'da, eski sürümlerde OOM'ye neden olması gereken bellek sızıntılarınız varsa, siz onu yakalayamadan çökecek gibi görünüyor. Bellek kullanımını şu şekilde kontrol edebilirsiniz:

val nativeHeapSize = Debug.getNativeHeapSize()
val nativeHeapFreeSize = Debug.getNativeHeapFreeSize()
val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize

Ancak, verileri gerçek zamanlı olarak bir grafik kullanarak gösteren IDE profil oluşturucusunu kullanmanın en iyisi olabileceğine inanıyorum.

Android O'daki iyi haber şu ki, OOM çok fazla büyük bitmap depolamasından dolayı çökmeler çok daha zor, ancak kötü haber şu ki, çalışma sırasında böyle bir durumu yakalamanın mümkün olduğunu düşünmüyorum.


DÜZENLE: Debug.getNativeHeapSize()Uygulamanız için toplam maksimum belleği gösterdiği için zamanla değişiyor gibi görünüyor . Dolayısıyla bu işlevler, uygulamanızın ne kadar kullandığını göstermek için yalnızca profil oluşturucu için kullanılır.

Gerçek toplamı ve mevcut yerel RAM'i almak istiyorsanız, şunu kullanın:

val memoryInfo = ActivityManager.MemoryInfo()
(getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(memoryInfo)
val nativeHeapSize = memoryInfo.totalMem
val nativeHeapFreeSize = memoryInfo.availMem
val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize
Log.d("AppLog", "total:${Formatter.formatFileSize(this, nativeHeapSize)} " +
        "free:${Formatter.formatFileSize(this, nativeHeapFreeSize)} " +
        "used:${Formatter.formatFileSize(this, usedMemInBytes)} ($usedMemInPercentage%)")

Vay. Çok basit ama çok doğru!
Ran

gerçek bellek kullanımı nedir? Bu durumda MemInMB, uygulamanın gerçek bellek kullanımı değil mi? Bu kodu kullandığımda kullanımın 50mb gibi olduğunu gösteriyor ancak telefon ayarlarına gidip oradaki bellek kullanımını gördüğümde uygulamam 100mb gösteriyor. bu fark neden?
batmaci

1
@batmaci Heap bellek, uygulamanın toplam bellek kullanımının sadece bir parçasıdır. Ayrıca genellikle Web sayfaları, oyunlar ve bazı ağır amaçlar için kullanılan yerel bellek kullanımı da vardır. Genellikle uygulamaların yalnızca yığın belleğe bakması gerekir, çünkü cihaz RAM'ine kıyasla oldukça düşüktür ve buna ulaşırlarsa, uygulama çökecektir (bol miktarda boş RAM olsa bile).
android geliştiricisi

Mükemmel bir kod parçacığı, OOM'yi kontrol etmek için çok kullanışlı, çok teşekkürler.
aolphn

@AlphaOF Teşekkürler, ancak Android O'da işler değişti. Cevabı oradaki duruma uyacak şekilde güncelledim.
android geliştiricisi

29

Şu anda çalışan uygulamanın bellek kullanımını hesaplamanın bir yolu :

public static long getUsedMemorySize() {

    long freeSize = 0L;
    long totalSize = 0L;
    long usedSize = -1L;
    try {
        Runtime info = Runtime.getRuntime();
        freeSize = info.freeMemory();
        totalSize = info.totalMemory();
        usedSize = totalSize - freeSize;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return usedSize;

}

4
Bu basit bir yaklaşımdır, ancak belgelerde belirtildiği gibi, Runtime sınıfı freeMemory () yöntemi, geçerli program veya uygulama için kullanılabilir belleği döndürür. Bu yüzden kullanırken bunun farkında olun.
Aksel Fatih

2
@Peter - Evet, sorulandan farklı bir soruyu yanıtladığı için "yanlış". Öte yandan, bu bir uygulama geliştiricisi genellikle bilmesi gerekenleri için "doğru" dir: nadiren DEVICE bellek genel halidir önemli olan - Kullanıcı uygulamalar çok yayınlanırsa OS gerektiğini en faydalanmak hafızası - aksi takdirde verimsiz olur. İşletim sisteminin, son zamanlarda kullanılmayan uygulamaları ne zaman sonlandırmaya başlayacağını bilmek için kabul edilen cevabın ne verdiğini bilmesi gerekir. Ancak bir uygulama programcısının runtime.maxMemory yerine BU yanıtın (ve android geliştiricinin benzer yanıtının) size ne söylediğini bilmesi gerekir.
ToolmakerSteve

Bu çözümler yalnızca Runtime tarafından uygulamaya maruz kalan bellek üzerinde çalışır. Bu, OP'nin gerektirdiği tüm sistem belleği hakkında fikir vermez.
AB

Birçok cihazda (örn. Xiaomi) Runtime.freeMemory()0 Runtime.totalMemory()döndürür ve yalnızca şu anda ayrılmış belleği döndürür.
artem

17

Başka bir yol (şu anda G1'imde 25MB boş gösteriliyor):

MemoryInfo mi = new MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;

Hey Alex, yardımın için çok teşekkürler! 1 soru daha. Bu kod bana kullanılabilir RAM veriyor. Ayrıca Toplam RAM'i görüntülemek istiyorum. Nasıl elde edilir?
Badal

@Badal Bunun için bir Java API bilmiyorum. Ayrıştırma / proc / meminfo'ya bağlı kalın.
yanchenko

12

Linux'un bellek yönetimi felsefesi "Boş bellek boşa harcanmış bellektir" dir.

Sonraki iki satırın "Tamponlarda" ne kadar bellek olduğunu ve ne kadarının "Önbelleğe Alınmış" olduğunu göstereceğini varsayıyorum. İkisi arasında bir fark olsa da (lütfen bu farkın ne olduğunu sormayın :) her ikisi de kabaca dosya verilerini ve meta verileri önbelleğe almak için kullanılan bellek miktarını ekler.

Bir Linux sisteminde belleği boşaltmak için çok daha kullanışlı bir kılavuz, free(1)komuttur; masaüstümde şu gibi bilgileri rapor ediyor:

$ free -m
             önbelleğe alınan toplam kullanılan ücretsiz paylaşılan arabellek sayısı
Mem: 5980 1055 4924 0 91374
- / + tamponlar / önbellek: 589 5391
Takas: 6347 0 6347

+/- tamponlar / önbellek: çizgisi sihirli çizgidir, gerçekten yaklaşık 589 mega aktif olarak gerekli işlem belleğine ve yaklaşık 5391 mega 'boş' belleğe sahip olduğumu bildiriyor, 91 + 374 megabayt Bellek başka bir yerde daha karlı bir şekilde kullanılabilirse, tamponlar / önbelleğe alınmış bellek atılabilir.

(Makinem yaklaşık üç saattir açık durumda, yığın aşımı dışında neredeyse hiçbir şey yapmıyor, bu yüzden çok fazla boş belleğim var.)

Android ile birlikte gönderilmezse free(1), hesaplamayı /proc/meminfodosya ile kendiniz yapabilirsiniz ; free(1)Çıktı formatını beğendim . :)


1
@Igor, o zaman cat /proc/meminfobunun yerine isteyeceksin . Çok daha ayrıntılı, ama MemFree. Buffersve Cachedmuhtemelen en önemli satırlardır.
sarnold

6

Birkaç yazıya atıfta bulunuyorum.

referans:

Bu getMemorySize () yöntemi, toplam ve boş bellek boyutuna sahip MemorySize döndürülür.
Bu koda tam olarak inanmıyorum.
Bu kod LG G3 cat.6 (v5.0.1) üzerinde test edilmektedir

    private MemorySize getMemorySize() {
        final Pattern PATTERN = Pattern.compile("([a-zA-Z]+):\\s*(\\d+)");

        MemorySize result = new MemorySize();
        String line;
        try {
            RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
            while ((line = reader.readLine()) != null) {
                Matcher m = PATTERN.matcher(line);
                if (m.find()) {
                    String name = m.group(1);
                    String size = m.group(2);

                    if (name.equalsIgnoreCase("MemTotal")) {
                        result.total = Long.parseLong(size);
                    } else if (name.equalsIgnoreCase("MemFree") || name.equalsIgnoreCase("Buffers") ||
                            name.equalsIgnoreCase("Cached") || name.equalsIgnoreCase("SwapFree")) {
                        result.free += Long.parseLong(size);
                    }
                }
            }
            reader.close();

            result.total *= 1024;
            result.free *= 1024;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    private static class MemorySize {
        public long total = 0;
        public long free = 0;
    }

Pattern.compile () 'ın pahalı olduğunu biliyorum, bu yüzden kodunu sınıf üyesine taşıyabilirsiniz.


3

Android Kaynak Ağacına baktım.

Com.android.server.am içinde. ActivityManagerService.java (android.app. ActivityManager tarafından sunulan dahili hizmet ).

public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
    final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
    final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
    outInfo.availMem = Process.getFreeMemory();
    outInfo.totalMem = Process.getTotalMemory();
    outInfo.threshold = homeAppMem;
    outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
    outInfo.hiddenAppThreshold = hiddenAppMem;
    outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
            ProcessList.SERVICE_ADJ);
    outInfo.visibleAppThreshold = mProcessList.getMemLevel(
            ProcessList.VISIBLE_APP_ADJ);
    outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
            ProcessList.FOREGROUND_APP_ADJ);
}

Android.os içinde. Process.java

/** @hide */
public static final native long getFreeMemory();

/** @hide */
public static final native long getTotalMemory();

Android_util_Process.cpp'den JNI yöntemini çağırır.

Sonuç

MemoryInfo.availMem = MemFree + / proc / meminfo'da önbelleğe alındı.

Notlar

Toplam Bellek, API düzeyi 16'da eklenir.


1

Android SDK'nın bir parçası olan DDMS aracını da kullanabilirsiniz. java kodu ve yerel c / c ++ kodunun bellek ayırmalarını elde etmeye de yardımcı olur.


0
public static boolean isAppInLowMemory(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);

    return memoryInfo.lowMemory;
}

0
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

Tuhaf bir kod. MaxMemory - (totalMemory - freeMemory) döndürür. FreeMemory, 0'a eşitse, kod MaxMemory - totalMemory'yi döndürecektir, böylece daha fazla olabilir veya 0'a eşit olabilir. FreeMemory neden kullanılmıyor?


0

İşte uygulamanızın bellek kullanımını görüntülemenin başka bir yolu:

adb shell dumpsys meminfo <com.package.name> -d

Örnek çıktı:

Applications Memory Usage (kB):
Uptime: 2896577 Realtime: 2896577

** MEMINFO in pid 2094 [com.package.name] **
                   Pss  Private  Private  Swapped     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap     3472     3444        0        0     5348     4605      102
  Dalvik Heap     2349     2188        0        0     4640     4486      154
 Dalvik Other     1560     1392        0        0
        Stack      772      772        0        0
    Other dev        4        0        4        0
     .so mmap     2749     1040     1220        0
    .jar mmap        1        0        0        0
    .apk mmap      218        0       32        0
    .ttf mmap       38        0        4        0
    .dex mmap     3161       80     2564        0
   Other mmap        9        4        0        0
      Unknown       76       76        0        0
        TOTAL    14409     8996     3824        0     9988     9091      256

 Objects
               Views:       30         ViewRootImpl:        2
         AppContexts:        4           Activities:        2
              Assets:        2        AssetManagers:        2
       Local Binders:       17        Proxy Binders:       21
    Death Recipients:        7
     OpenSSL Sockets:        0

 SQL
         MEMORY_USED:        0
  PAGECACHE_OVERFLOW:        0          MALLOC_SIZE:        0

Genel bellek kullanımı için:

adb shell dumpsys meminfo

https://developer.android.com/studio/command-line/dumpsys#meminfo

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.