dumpsys meminfo 解析

1.命令執行輸出

sssss:/ # dumpsys meminfo com.android.home                                                                                                                                              
Applications Memory Usage (in Kilobytes):
Uptime: 5285433 Realtime: 6628897

** MEMINFO in pid 5049 [com.android.home] **
                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap    63416    63204        0        0   113664    77388    36275
  Dalvik Heap     4859     4820        0        0     7057     5309     1748
 Dalvik Other     3949     3948        0        0                           
        Stack       56       56        0        0                           
       Ashmem       10        8        0        0                           
      Gfx dev     8192     8192        0        0                           
    Other dev      108        0      108        0                           
     .so mmap     3031      288      128        0                           
    .jar mmap        0        0        0        0                           
    .apk mmap    22175        0    19504        0                           
    .ttf mmap     1310        0      256        0                           
    .dex mmap     8945       12     7760        0                           
    .oat mmap     4191        0      192        0                           
    .art mmap     3340     2880        0        0                           
   Other mmap      315       12      176        0                           
    GL mtrack    10444    10444        0        0                           
      Unknown     1282     1276        0        0                           
        TOTAL   135623    95140    28124        0   120721    82697    38023
 
 App Summary
                       Pss(KB)
                        ------
           Java Heap:     7700
         Native Heap:    63204
                Code:    28140
               Stack:       56
            Graphics:    18636
       Private Other:     5528
              System:    12359
 
               TOTAL:   135623       TOTAL SWAP PSS:        0
 
 Objects
               Views:      789         ViewRootImpl:        1
         AppContexts:        8           Activities:        1
              Assets:       13        AssetManagers:        0
       Local Binders:       62        Proxy Binders:       40
       Parcel memory:       13         Parcel count:       56
    Death Recipients:        2      OpenSSL Sockets:        0
            WebViews:        0
 
 SQL
         MEMORY_USED:      618
  PAGECACHE_OVERFLOW:      129          MALLOC_SIZE:      117
 
 DATABASES
      pgsz     dbsz   Lookaside(b)          cache  Dbname
         4       28             37        43/24/4  /data/user_de/0/com.android.home/databases/est_ev
         4       36             93     637/327/25  /data/user_de/0/com.android.home/databases/launcher.db

主要關注 Native heap 和 Dalvik heap/Java heap 的數據從哪裏拿的。

這個數據,其實都是在 ActivityManagerService.java的 dumpMemInfoTable函數中打印的。

 

2.Native/Dalvik heap的 size/allocated/free 數據

                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap    63416    63204        0        0   113664    77388    36275

比如這個數據,其實是在 ActivityManagerService.java的 dumpMemInfoTable函數中如下代碼打印的:

                printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
                        "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
                        "Heap", "Heap", "Heap");
                printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
                        "Clean", "Dirty", "Size", "Alloc", "Free");
                printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
                        "------", "------", "------", "------", "------");
                printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
                        memInfo.nativePrivateDirty,
                        memInfo.nativePrivateClean,
                        memInfo.hasSwappedOutPss ? memInfo.nativeSwappedOutPss :
                        memInfo.nativeSwappedOut,
                        nativeMax, nativeAllocated, nativeFree);
                printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
                        memInfo.dalvikPrivateDirty,
                        memInfo.dalvikPrivateClean,
                        memInfo.hasSwappedOutPss ? memInfo.dalvikSwappedOutPss :
                        memInfo.dalvikSwappedOut,
                        dalvikMax, dalvikAllocated, dalvikFree);

可以看到 Native Heap的數據都是從 memInfo的如下幾個成員拿到的:

                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
Native Heap     nativePss  nativePrivateDirty nativePrivateClean   nativeSwappedOut  nativeMax    nativeAllocated    nativeFree
Dalvik Heap     dalvikPss  dalvikPrivateDirty dalvikPrivateClean   dalvikSwappedOut  dalvikMax    dalvikAllocated    dalvikFree

最後三個數據(max /allocated/free)的獲取:

            long nativeMax = Debug.getNativeHeapSize() / 1024;
            long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
            long nativeFree = Debug.getNativeHeapFreeSize() / 1024;

            Runtime runtime = Runtime.getRuntime();
            runtime.gc();  // Do GC since countInstancesOfClass counts unreachable objects.
            long dalvikMax = runtime.totalMemory() / 1024;
            long dalvikFree = runtime.freeMemory() / 1024;
            long dalvikAllocated = dalvikMax - dalvikFree;

2.1 native heap的三個函數都是 jni實現的:

static jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz)
{
    struct mallinfo info = mallinfo();
    return (jlong) info.usmblks;
}

static jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject clazz)
{
    struct mallinfo info = mallinfo();
    return (jlong) info.uordblks;
}

static jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
{
    struct mallinfo info = mallinfo();
    return (jlong) info.fordblks;
}

這個mallinfo 實際是用的 je_mallinfo:

(gdb) bt
#0  je_mallinfo () at external/jemalloc/src/android_je_mallinfo.c:22
#1  0x000000733cf2359c in android::android_os_Debug_getNativeHeapSize (env=0x0 <_DYNAMIC>, clazz=0x729e37f7c4) at frameworks/base/core/jni/android_os_Debug.cpp:169
#2  0x00000000759d1874 in android.app.backup.FileBackupHelperBase.ctor [DEDUPED] () from out-cepheus/target/product/cepheus/symbols/system/framework/arm64/boot-framework.oat
#3  0x00000000764f0780 in android.app.ActivityThread$ApplicationThread.dumpMemInfo () from out-cepheus/target/product/cepheus/symbols/system/framework/arm64/boot-framework.oat
#4  0x00000000764f2c74 in android.app.ActivityThread$ApplicationThread.dumpMemInfo () from out-cepheus/target/product/cepheus/symbols/system/framework/arm64/boot-framework.oat

我們查看一下 je_mallinfo:

(gdb) call je_mallinfo()
$1 = {
  arena = 0, 
  ordblks = 0, 
  smblks = 0, 
  hblks = 0, 
  hblkhd = 116391936, 
  usmblks = 116391936, 
  fsmblks = 0, 
  uordblks = 79656472, 
  fordblks = 36735464, 
  keepcost = 0
}

(gdb) p 116391936/1024
$3 = 113664
(gdb) p 79656472/1024
$4 = 77789
(gdb) p 36735464/1024
$5 = 35874
(gdb) p 116391936-79656472
$6 = 36735464

所以:
    long nativeMax = Debug.getNativeHeapSize() / 1024 = 113664 KB;
    long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024 = 77789 KB;
    long nativeFree = Debug.getNativeHeapFreeSize() / 1024 = 35874 KB;

這個數據獲取的時候,與上面貼的數據, allocated和free有一點區別,可以忽略,因爲不是同一次獲取的。

2.2 dalvik部分:

dalvik heap size的獲取用到了兩個函數:

            long dalvikMax = runtime.totalMemory() / 1024;
            long dalvikFree = runtime.freeMemory() / 1024;
            long dalvikAllocated = dalvikMax - dalvikFree;

對應的實現是:

size_t Heap::GetTotalMemory() const {
  return std::max(max_allowed_footprint_, GetBytesAllocated());
}
  size_t GetBytesAllocated() const {
    return num_bytes_allocated_.LoadSequentiallyConsistent();
  }

  size_t GetFreeMemory() const {
    size_t byte_allocated = num_bytes_allocated_.LoadSequentiallyConsistent();
    size_t total_memory = GetTotalMemory();
    // Make sure we don't get a negative number.
    return total_memory - std::min(total_memory, byte_allocated);
  }

  size_t GetMaxMemory() const {
    // There is some race conditions in the allocation code that can cause bytes allocated to
    // become larger than growth_limit_ in rare cases.
    return std::max(GetBytesAllocated(), growth_limit_);
  }


(gdb) p 'art::Runtime'::instance_->heap_->max_allowed_footprint_
$3 = 7226368
(gdb) p 'art::Runtime'::instance_->heap_->num_bytes_allocated_.__a_
$8 = 5436416
(gdb) p 'art::Runtime'::instance_->heap_->growth_limit_
$7 = 536870912
(gdb) p 'art::Runtime'::instance_->heap_->capacity_
$12 = 536870912
(gdb) p 536870912/1024/1024
$14 = 512
這裏當前進程的 growth_limit_ 和 heap_size都是 512M

對應的上面三個數據是:

            long dalvikMax = runtime.totalMemory() / 1024 = 7057 KB;
            long dalvikFree = runtime.freeMemory() / 1024 = 5309 KB;
            long dalvikAllocated = dalvikMax - dalvikFree = 1748 KB;

3.Native/Dalvik Heap的詳細數據獲取

主要解釋 Size,Alloc,Free前面的幾個數據的獲取:

                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap    63416    63204        0        0   113664    77388    36275
  Dalvik Heap     4859     4820        0        0     7057     5309     1748

獲取方式如下:

                printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
                        memInfo.nativePrivateDirty,
                        memInfo.nativePrivateClean,
                        memInfo.hasSwappedOutPss ? memInfo.nativeSwappedOutPss :
                        memInfo.nativeSwappedOut,
                        nativeMax, nativeAllocated, nativeFree);
                printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
                        memInfo.dalvikPrivateDirty,
                        memInfo.dalvikPrivateClean,
                        memInfo.hasSwappedOutPss ? memInfo.dalvikSwappedOutPss :
                        memInfo.dalvikSwappedOut,
                        dalvikMax, dalvikAllocated, dalvikFree);

memInfo其實是從如下函數獲取:

   Debug.getMemoryInfo(pid, mi);

    { "getMemoryInfo",          "(ILandroid/os/Debug$MemoryInfo;)V",
            (void*) android_os_Debug_getDirtyPagesPid },

對應實現在:android_os_Debug_getDirtyPagesPid

static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
        jint pid, jobject object)
{
    bool foundSwapPss;
    stats_t stats[_NUM_HEAP];
    memset(&stats, 0, sizeof(stats));

    load_maps(pid, stats, &foundSwapPss);
    ...
    for (int i=0; i<_NUM_CORE_HEAP; i++) {
        env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss);
        env->SetIntField(object, stat_fields[i].pssSwappable_field, stats[i].swappablePss);
        env->SetIntField(object, stat_fields[i].rss_field, stats[i].rss);
        env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
        env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
        env->SetIntField(object, stat_fields[i].privateClean_field, stats[i].privateClean);
        env->SetIntField(object, stat_fields[i].sharedClean_field, stats[i].sharedClean);
        env->SetIntField(object, stat_fields[i].swappedOut_field, stats[i].swappedOut);
        env->SetIntField(object, stat_fields[i].swappedOutPss_field, stats[i].swappedOutPss);
    }
    ...
}

static void load_maps(int pid, stats_t* stats, bool* foundSwapPss)
{
    *foundSwapPss = false;

    std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid);
    UniqueFile fp = MakeUniqueFile(smaps_path.c_str(), "re");
    if (fp == nullptr) return;

    read_mapinfo(fp.get(), stats, foundSwapPss);
}

可以看到其實是讀取 "/proc/pid/smaps",進行分析統計的。

實現如下:

static void read_mapinfo(FILE *fp, stats_t* stats, bool* foundSwapPss)
{
   ...
    if(fgets(line, sizeof(line), fp) == 0) return;

    while (!done) {
       ...
        if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
            skip = true;
        } else {
            while (isspace(line[name_pos])) {
                name_pos += 1;
            }
            name = line + name_pos;
            nameLen = strlen(name);
            // Trim the end of the line if it is " (deleted)".
            const char* deleted_str = " (deleted)";
            if (nameLen > (int)strlen(deleted_str) &&
                strcmp(name+nameLen-strlen(deleted_str), deleted_str) == 0) {
                nameLen -= strlen(deleted_str);
                name[nameLen] = '\0';
            }
            if ((strstr(name, "[heap]") == name)) {
                whichHeap = HEAP_NATIVE;
            } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
                whichHeap = HEAP_NATIVE;
            } else if (strncmp(name, "[stack", 6) == 0) {
                whichHeap = HEAP_STACK;
            } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
                whichHeap = HEAP_SO;
                is_swappable = true;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) {
                whichHeap = HEAP_JAR;
                is_swappable = true;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) {
                whichHeap = HEAP_APK;
                is_swappable = true;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) {
                whichHeap = HEAP_TTF;
                is_swappable = true;
            } else if ((nameLen > 4 && strstr(name, ".dex") != NULL) ||
                       (nameLen > 5 && strcmp(name+nameLen-5, ".odex") == 0)) {
                whichHeap = HEAP_DEX;
                subHeap = HEAP_DEX_APP_DEX;
                is_swappable = true;
            } else if (nameLen > 5 && strcmp(name+nameLen-5, ".vdex") == 0) {
                whichHeap = HEAP_DEX;
                // Handle system@framework@boot* and system/framework/boot*
                if (strstr(name, "@boot") != NULL || strstr(name, "/boot") != NULL) {
                    subHeap = HEAP_DEX_BOOT_VDEX;
                } else {
                    subHeap = HEAP_DEX_APP_VDEX;
                }
                is_swappable = true;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".oat") == 0) {
                whichHeap = HEAP_OAT;
                is_swappable = true;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".art") == 0) {
                whichHeap = HEAP_ART;
                // Handle system@framework@boot* and system/framework/boot*
                if (strstr(name, "@boot") != NULL || strstr(name, "/boot") != NULL) {
                    subHeap = HEAP_ART_BOOT;
                } else {
                    subHeap = HEAP_ART_APP;
                }
                is_swappable = true;
            } else if (strncmp(name, "/dev/", 5) == 0) {
                if (strncmp(name, "/dev/kgsl-3d0", 13) == 0) {
                    whichHeap = HEAP_GL_DEV;
                } else if (strncmp(name, "/dev/ashmem", 11) == 0) {
                    if (strncmp(name, "/dev/ashmem/dalvik-", 19) == 0) {
                        whichHeap = HEAP_DALVIK_OTHER;
                        if (strstr(name, "/dev/ashmem/dalvik-LinearAlloc") == name) {
                            subHeap = HEAP_DALVIK_OTHER_LINEARALLOC;
                        } else if ((strstr(name, "/dev/ashmem/dalvik-alloc space") == name) ||
                                   (strstr(name, "/dev/ashmem/dalvik-main space") == name)) {
                            // This is the regular Dalvik heap.
                            whichHeap = HEAP_DALVIK;
                            subHeap = HEAP_DALVIK_NORMAL;
                        } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name ||
                                   strstr(name, "/dev/ashmem/dalvik-free list large object space")
                                       == name) {
                            whichHeap = HEAP_DALVIK;
                            subHeap = HEAP_DALVIK_LARGE;
                        } else if (strstr(name, "/dev/ashmem/dalvik-non moving space") == name) {
                            whichHeap = HEAP_DALVIK;
                            subHeap = HEAP_DALVIK_NON_MOVING;
                        } else if (strstr(name, "/dev/ashmem/dalvik-zygote space") == name) {
                            whichHeap = HEAP_DALVIK;
                            subHeap = HEAP_DALVIK_ZYGOTE;
                        } else if (strstr(name, "/dev/ashmem/dalvik-indirect ref") == name) {
                            subHeap = HEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE;
                        } else if (strstr(name, "/dev/ashmem/dalvik-jit-code-cache") == name ||
                                   strstr(name, "/dev/ashmem/dalvik-data-code-cache") == name) {
                            subHeap = HEAP_DALVIK_OTHER_CODE_CACHE;
                        } else if (strstr(name, "/dev/ashmem/dalvik-CompilerMetadata") == name) {
                            subHeap = HEAP_DALVIK_OTHER_COMPILER_METADATA;
                        } else {
                            subHeap = HEAP_DALVIK_OTHER_ACCOUNTING;  // Default to accounting.
                        }
                    } else if (strncmp(name, "/dev/ashmem/CursorWindow", 24) == 0) {
                        whichHeap = HEAP_CURSOR;
                    } else if (strncmp(name, "/dev/ashmem/libc malloc", 23) == 0) {
                        whichHeap = HEAP_NATIVE;
                    } else {
                        whichHeap = HEAP_ASHMEM;
                    }
                } else {
                    whichHeap = HEAP_UNKNOWN_DEV;
                }
            } else if (strncmp(name, "[anon:", 6) == 0) {
                whichHeap = HEAP_UNKNOWN;
            } else if (nameLen > 0) {
                whichHeap = HEAP_UNKNOWN_MAP;
            } else if (start == prevEnd && prevHeap == HEAP_SO) {
                // bss section of a shared library.
                whichHeap = HEAP_SO;
            }
        }
   ...
        while (true) {
            if (fgets(line, 1024, fp) == 0) {
                done = true;
                break;
            }

            if (line[0] == 'S' && sscanf(line, "Size: %d kB", &temp) == 1) {
                /* size = temp; */
            } else if (line[0] == 'R' && sscanf(line, "Rss: %d kB", &temp) == 1) {
                rss = temp;
            } else if (line[0] == 'P' && sscanf(line, "Pss: %d kB", &temp) == 1) {
                pss = temp;
            } else if (line[0] == 'S' && sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
                shared_clean = temp;
            } else if (line[0] == 'S' && sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
                shared_dirty = temp;
            } else if (line[0] == 'P' && sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
                private_clean = temp;
            } else if (line[0] == 'P' && sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
                private_dirty = temp;
            } else if (line[0] == 'R' && sscanf(line, "Referenced: %d kB", &temp) == 1) {
                /* referenced = temp; */
            } else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
                swapped_out = temp;
            } else if (line[0] == 'S' && sscanf(line, "SwapPss: %d kB", &temp) == 1) {
                *foundSwapPss = true;
                swapped_out_pss = temp;
            } else if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
                // looks like a new mapping
                // example: "10000000-10001000 ---p 10000000 00:00 0"
                break;
            }
        }
   ...
        if (!skip) {
            if (is_swappable && (pss > 0)) {
                sharing_proportion = 0.0;
                if ((shared_clean > 0) || (shared_dirty > 0)) {
                    sharing_proportion = (pss - private_clean
                            - private_dirty)/(shared_clean+shared_dirty);
                }
                swappable_pss = (sharing_proportion*shared_clean) + private_clean;
            } else
                swappable_pss = 0;

            stats[whichHeap].pss += pss;
            stats[whichHeap].swappablePss += swappable_pss;
            stats[whichHeap].rss += rss;
            stats[whichHeap].privateDirty += private_dirty;
            stats[whichHeap].sharedDirty += shared_dirty;
            stats[whichHeap].privateClean += private_clean;
            stats[whichHeap].sharedClean += shared_clean;
            stats[whichHeap].swappedOut += swapped_out;
            stats[whichHeap].swappedOutPss += swapped_out_pss;
            if (whichHeap == HEAP_DALVIK || whichHeap == HEAP_DALVIK_OTHER ||
                    whichHeap == HEAP_DEX || whichHeap == HEAP_ART) {
                stats[subHeap].pss += pss;
                stats[subHeap].swappablePss += swappable_pss;
                stats[subHeap].rss += rss;
                stats[subHeap].privateDirty += private_dirty;
                stats[subHeap].sharedDirty += shared_dirty;
                stats[subHeap].privateClean += private_clean;
                stats[subHeap].sharedClean += shared_clean;
                stats[subHeap].swappedOut += swapped_out;
                stats[subHeap].swappedOutPss += swapped_out_pss;
            }
        }
}

Dalvik Heap和Native Heap的數據都來自 stats[HEAP_DALVIK] 和 stats[HEAP_NATIVE];

可以看到read_mapinfo中主要是讀取 smaps中各個段的不同信息來進行統計;

查看smaps中一個歸屬於 Dalvik Heap的段的信息:

12c00000-12f40000 rw-p 00000000 00:05 36382                              /dev/ashmem/dalvik-main space (region space) (deleted)                                                         
Size:               3328 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                2708 kB

//Dalvik Heap的 Pss Total數據就是smaps中所有屬於 dalvik 段的 Pss數值的總和,Native heap的類似
Pss:                2708 kB   
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:      2708 kB
Referenced:         2708 kB
Anonymous:          2708 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
VmFlags: rd wr mr mw me ac

屬於Native Heap的內存段的數據類似:

728ac00000-728b000000 rw-p 00000000 00:00 0                              [anon:libc_malloc]
Name:           [anon:libc_malloc]
Name:           [anon:libc_malloc]
Size:               4096 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                1736 kB
Pss:                1736 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:      1736 kB
Referenced:         1736 kB
Anonymous:          1736 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
VmFlags: rd wr mr mw me nr 

4.App Summary

App Summary對數據又做了一些合併處理:

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     7700
         Native Heap:    63204
                Code:    28140
               Stack:       56
            Graphics:    18636
       Private Other:     5528
              System:    12359
 
               TOTAL:   135623       TOTAL SWAP PSS:        0

其數據獲取方式如下:

        pw.println(" App Summary");
        printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "Pss(KB)");
        printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "------");
        printRow(pw, ONE_COUNT_COLUMN,
            "Java Heap:", memInfo.getSummaryJavaHeap());
        printRow(pw, ONE_COUNT_COLUMN,
            "Native Heap:", memInfo.getSummaryNativeHeap());
        printRow(pw, ONE_COUNT_COLUMN,
            "Code:", memInfo.getSummaryCode());
        printRow(pw, ONE_COUNT_COLUMN,
            "Stack:", memInfo.getSummaryStack());
        printRow(pw, ONE_COUNT_COLUMN,
            "Graphics:", memInfo.getSummaryGraphics());
        printRow(pw, ONE_COUNT_COLUMN,
            "Private Other:", memInfo.getSummaryPrivateOther());
        printRow(pw, ONE_COUNT_COLUMN,
            "System:", memInfo.getSummarySystem());
        pw.println(" ");
        if (memInfo.hasSwappedOutPss) {
            printRow(pw, TWO_COUNT_COLUMNS,
                "TOTAL:", memInfo.getSummaryTotalPss(),
                "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
        } else {
            printRow(pw, TWO_COUNT_COLUMNS,
                "TOTAL:", memInfo.getSummaryTotalPss(),
                "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
        }

這裏根據每個數據的獲取看一下他們的涵義:

        public int getSummaryJavaHeap() {
            return dalvikPrivateDirty + getOtherPrivate(OTHER_ART);
        }

        public int getSummaryNativeHeap() {
            return nativePrivateDirty;
        }

        public int getSummaryCode() {
            return getOtherPrivate(OTHER_SO)
              + getOtherPrivate(OTHER_JAR)
              + getOtherPrivate(OTHER_APK)
              + getOtherPrivate(OTHER_TTF)
              + getOtherPrivate(OTHER_DEX)
              + getOtherPrivate(OTHER_OAT);
        }

        public int getSummaryStack() {
            return getOtherPrivateDirty(OTHER_STACK);
        }

        public int getSummaryGraphics() {
            return getOtherPrivate(OTHER_GL_DEV)
              + getOtherPrivate(OTHER_GRAPHICS)
              + getOtherPrivate(OTHER_GL);
        }
        public int getSummaryPrivateOther() {
            return getTotalPrivateClean()
              + getTotalPrivateDirty()
              - getSummaryJavaHeap()
              - getSummaryNativeHeap()
              - getSummaryCode()
              - getSummaryStack()
              - getSummaryGraphics();
        }

        public int getSummarySystem() {
            return getTotalPss()
              - getTotalPrivateClean()
              - getTotalPrivateDirty();
        }

        public int getSummaryTotalPss() {
            return getTotalPss();
        }

這些 OTHER_ART,OTHER_SO,OTHER_JAR等類型內存的分類參考前面 read_mapinfo的分類即可。

 

其餘 dumpsys meminfo 的實現待調研。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章