Android Memory Tracker原理分析

1. 背景

公司有一個測試項,執(zhí)行adb shell dumpsys meminfo + pkg命令查看內存信息:

malk@malk:am$ adb shell dumpsys meminfo com.meizu.safe
Applications Memory Usage (in Kilobytes):
Uptime: 103881237 Realtime: 263009590

** MEMINFO in pid 32506 [com.meizu.safe] **
                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap    18894    18832        0        0    32768    20940    11827
  Dalvik Heap     6713     6624        0        0    10615     6519     4096
 Dalvik Other     1485     1484        0        0                           
        Stack      700      700        0        0                           
       Ashmem        2        0        0        0                           
    Other dev        4        0        4        0                           
     .so mmap     2717      136       40       39                           
    .apk mmap    44952        0    35456        0                           
    .ttf mmap       45        0        0        0                           
    .dex mmap     5344        8     1324        0                           
    .oat mmap     2728        0        0        0                           
    .art mmap     2871     2368        4        2                           
   Other mmap     1090        4       64        0                           
   EGL mtrack    12168    12168        0        0                           
      Unknown     1535     1532        0        0                           
        TOTAL   101289    43856    36892       41    43383    27459    15923

 App Summary
                       Pss(KB)
                        ------
           Java Heap:     8996
         Native Heap:    18832
                Code:    36964
               Stack:      700
            Graphics:    12168
       Private Other:     3088
              System:    20541

               TOTAL:   101289       TOTAL SWAP PSS:       41

一直有個疑問,dump信息中EGL mtrack/GL mtrack兩項分別代表什么意思诚隙?

google官方解釋:
EGL memtrack

You will see this column when display driver’s memtrack module is enabled
Before Lollipop5.1, this column is named “Graphics”.
EGL memtrack memory is the summary of all surface buffers(the surface buffer increases to triple buffer after Android 4.1) and the size of the Atlas buffer. 
However, Atlas buffer is actually a shared memory and shouldn’t be accounted into each UI process’ memory usage to overcount the memory usage. 
Both surface buffer and Atlas buffer’s memory quota is reserved in project’s memory estimation, thus the memory usage of these buffers should be separately 
accounted from process’ memory usage. So when you measure process’ memory usage, you can ignore this column.

GL memtrack

You will see this column when display driver’s memtrack module is enabled
Before Lollipop5.1, this column is named “GL”.
HW acceleration memory is partially counted in process PSS. For example, for QCT platform the HW acceleration memory is partially counted in the PSS of /dev/kgsl-3d0 
as we mentioned in the “Gfx dev” section. GL memtrack memory usage calculates the unaccounted /dev/kgsl-3d0 memory regions which PSS value equals 0.
Please be noticed that the summation of GL memtrack and Gfx dev doesn’t reflect the complete HW acceleration memory since the full HW acceleration memory usage 
should be counted with the VSS of /dev/kgsl-3d0. So the “TOTAL” value of dumpsys meminfo is smaller than actual physical memory usage.

只看簡介有些難以理解召噩,我想了解它的生成原理纸兔,找了半天省有,發(fā)現(xiàn)qualcomm和mtk平臺相關代碼沒有開源,還好samsung開源了代碼。

先說明一下這兩項的含義:

name description
EGL mtrack gralloc分配的內存胞得,主要是窗口系統(tǒng),SurfaceView/TextureView和其他的由gralloc分配的GraphicBuffer總和
GL mtrack 驅動上報的GL內存使用情況屹电。 主要是GL texture大小阶剑,GL command buffer,固定的全局驅動程序RAM開銷等的總和

2. Memory Tracker

2.1 Memory Tracker是什么

Memory Tracker也稱memtrack危号,是一個hal層的庫牧愁,不同平臺庫的名稱不同,實現(xiàn)方式也有差異外莲。

以samsung平臺為例:

Name: memtrack.exynos5.so
File Directory:/system/lib64/hw/
Source code : hardware/samsung_slsi/exynos/libmemtrack/

Memory Tracker 主要目標是能夠跟蹤以任何其他方式無法跟蹤的內存猪半,例如由進程分配但未映射到進程地址空間的紋理內存。
第二個目標是能夠將進程使用的內存分類為GL偷线,graphics等磨确。所有的內存大小應該在實際的內存使用情況下,考慮到stride声邦,bit depth乏奥,page size等。

EGL mtrack/GL mtrack這兩項的數(shù)據(jù)就是通過memtrack獲取的亥曹。

2.2 adb shell dumpsys meminfo實現(xiàn)原理

先看一下adb shell dumpsys meminfo +pkg的流程

這里寫圖片描述

1. Ams在systemserver啟動時邓了,創(chuàng)建了meminfo服務,所以才能dumpsys meminfo:

ServiceManager.addService("meminfo", new MemBinder(this));

2.執(zhí)行dumpsys操作后媳瞪,會去獲取兩部分信息:

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);//獲取/proc/$pid/smap節(jié)點信息

    struct graphics_memory_pss graphics_mem;
    if (read_memtrack_memory(pid, &graphics_mem) == 0) {//獲取graphics drivers上報的內存信息
        stats[HEAP_GRAPHICS].pss = graphics_mem.graphics;
        stats[HEAP_GRAPHICS].privateDirty = graphics_mem.graphics;
        stats[HEAP_GL].pss = graphics_mem.gl;
        stats[HEAP_GL].privateDirty = graphics_mem.gl;
        stats[HEAP_OTHER_MEMTRACK].pss = graphics_mem.other;
        stats[HEAP_OTHER_MEMTRACK].privateDirty = graphics_mem.other;
    }
}
static void load_maps(int pid, stats_t* stats, bool* foundSwapPss)
{
    char tmp[128];
    FILE *fp;

    sprintf(tmp, "/proc/%d/smaps", pid);
    fp = fopen(tmp, "r");
    if (fp == 0) return;

    read_mapinfo(fp, stats, foundSwapPss);
    fclose(fp);
}
/*
 * Retrieves the graphics memory that is unaccounted for in /proc/pid/smaps.
 * 獲取不計算在/proc/pid/smaps里的graphics memory信息
 */
static int read_memtrack_memory(int pid, struct graphics_memory_pss* graphics_mem)
{
    if (!memtrackLoaded) {
        return -1;
    }

    struct memtrack_proc* p = memtrack_proc_new();
    if (p == NULL) {
        ALOGW("failed to create memtrack_proc");
        return -1;
    }

    int err = read_memtrack_memory(p, pid, graphics_mem);
    memtrack_proc_destroy(p);
    return err;
}

3. graphics memory數(shù)據(jù)類型
graphics memory分為五種類型數(shù)據(jù):

  • MEMTRACK_TYPE_OTHER = 0
  • MEMTRACK_TYPE_GL = 1
  • MEMTRACK_TYPE_GRAPHICS = 2
  • MEMTRACK_TYPE_MULTIMEDIA = 3
  • MEMTRACK_TYPE_CAMERA = 4

我看到libmemtrack中有判斷骗炉,只接收兩種數(shù)據(jù),其他數(shù)據(jù)對應的代碼沒有找到:

memtrack_exynos.c
    if (type == MEMTRACK_TYPE_GL) {
        return mali_memtrack_get_memory(pid, type, records, num_records);
    } else if (type == MEMTRACK_TYPE_GRAPHICS) {
        return ion_memtrack_get_memory(pid, type, records, num_records);
    }

MEMTRACK_TYPE_GL = GL mtrack材失,MEMTRACK_TYPE_GRAPHICS = EGL mstrack

2.3 Memory Tracker實現(xiàn)原理

graphics memory的數(shù)據(jù)是由graphics driver統(tǒng)計的痕鳍,統(tǒng)計方式會因平臺不同而有所差異硫豆,即使相同應用龙巨,不同平臺讀取的數(shù)據(jù)也可能不相同笼呆。
Memory Tracker做的事情就是將graphics driver統(tǒng)計好的數(shù)據(jù)從節(jié)點讀取并格式化。

以samsung平臺為例旨别,memtrack.exynos5.so庫做的事情很簡單诗赌,根據(jù)上層傳遞的type讀取對應節(jié)點,獲取內存信息秸弛。

memtrack_exynos.c
    if (type == MEMTRACK_TYPE_GL) {
        return mali_memtrack_get_memory(pid, type, records, num_records);
    } else if (type == MEMTRACK_TYPE_GRAPHICS) {
        return ion_memtrack_get_memory(pid, type, records, num_records);
    }

2.3.1 MEMTRACK_TYPE_GL

如果上層傳遞的type類型為MEMTRACK_TYPE_GL铭若,對應GL mtrack,說明需要獲取的是驅動程序報告的GL內存使用递览。它主要是GL紋理大小叼屠,GL命令緩沖區(qū),固定的全局驅動程序RAM開銷等的總和绞铃。這些數(shù)據(jù)儲存在/d/mali/mem/目錄下的節(jié)點中(samsung)镜雨,由mali庫(或者其他平臺的渲染庫)進行統(tǒng)計。

以samsung平臺儿捧,com.meizu.safe應用為例荚坞,我們查看其數(shù)據(jù):

1|m17:/ # ps | grep safe                                                                                                                                                              
system    32459 1174  1849812 127628 SyS_epoll_ 7b483472a0 S com.meizu.safe:MzSecService
system    32506 1174  2904076 225528 SyS_epoll_ 7b483472a0 S com.meizu.safe
m17:/ # 
m17:/ # 
m17:/ # cat /d/mali/mem/32506_76/mem_profile                                                                                                                                          
com.meizu.safe:
Channel: Unnamed (Total memory: 2384536)
  7:                  226 / 14464
  8:                  297 / 47520
  9:                   16 / 6272
 13:                  166 / 684696
 14:                   68 / 601960
 15:                    4 / 79352
 16:                    3 / 98304
 17:                    5 / 327680
 18:                    4 / 524288

Channel: Default Heap (Total memory: 1678048)
 13:                   14 / 60744
 14:                    2 / 27352
 16:                    6 / 196672
 18:                    4 / 749088
 20:                    1 / 644192

Channel: Framepool (Total memory: 0)
 (empty)

Channel: Frame Internal (Total memory: 32768)
 16:                    1 / 32768

Channel: GPU Program (Total memory: 40960)
 16:                    1 / 40960

Channel: EGL Color Plane (Total memory: 4096)
 13:                    1 / 4096

Channel: GLES VAO (Total memory: 0)
 (empty)

Channel: Image Descriptor (Total memory: 352)
  5:                   16 / 256
  7:                    1 / 96

Channel: Texture (Total memory: 6252064)
  6:                    1 / 32
 10:                    1 / 512
 11:                    1 / 1024
 12:                    1 / 2048
 14:                    2 / 18816
 16:                    1 / 51008
 17:                    7 / 716608
 19:                    1 / 266240
 21:                    1 / 1048576
 22:                    1 / 4147200

Channel: Buffer (Total memory: 1204288)
  7:                    1 / 64
 15:                    1 / 24576
 18:                    1 / 131072
 21:                    1 / 1048576

Channel: CRC Buffer (Total memory: 102400)
 13:                    1 / 4096
 16:                    3 / 98304

Total allocated memory: 11699512

分類說明:

name description
Default Heap gpu內部結構的內存分配。是gpu中最基礎的內存分配
Framepool framepool是gpu內部的概念菲盾,這個channel統(tǒng)計為framepool結構分配的內存颓影。很多函數(shù),例如eglSwapBuffers可能會引起這個channel的內存增加
Frame Internal tiler是gpu內部的概念懒鉴,這個channel統(tǒng)計為tiler結構分配的內存诡挂。很多函數(shù),例如glCreateXXXSurface可能會引起這個channel的內存增加
GPU Program glLinkProgram被調用時临谱,需要分配相應內存來存放shader code咆畏,那么這段內存將被記錄進GPU Program
Image Descriptor image instance是gpu內部的概念,這個channel統(tǒng)計為image instance結構分配的內存吴裤。很多函數(shù)旧找,例如glDrawXXX可能會引起這個channel的內存增加
EGL Color Plane 為color planes分配的內部buffer。一些函數(shù)麦牺,例如gpu的回調函數(shù)可能會引起這個channel的內存增加
GLES VAO VAO是一個保存了所有頂點數(shù)據(jù)屬性的狀態(tài)結合钮蛛,它存儲了頂點數(shù)據(jù)的格式以及頂點數(shù)據(jù)所需的VBO對象的引用。
Texture 紋理
Buffer glBufferData被調用時剖膳,需要分配內存來存放要導入的data魏颓,這段內存將被記錄進Buffer
CRC Buffer 一個color buffer的CRC buffer。一些函數(shù)吱晒,例如gpu的回調函數(shù)可能會引起這個channel的內存增加

2.3.1 MEMTRACK_TYPE_GRAPHICS

MEMTRACK_TYPE_GRAPHICS對應EGL mtrack甸饱,獲取的是gralloc內存使用情況。這些數(shù)據(jù)儲存在/sys/kernel/debug/ion/clients/目錄的節(jié)點下(samsung)。

首先說明叹话,graphic memory由進程觸發(fā)分配偷遗,但是不會映射到進程的地址空間。
但是計算時驼壶,這部分內存可能會計算到應用的內存中氏豌。

以samsung平臺為例:
對于沒有TextureView和SurfaceView的應用,這個數(shù)值的大小應該是系統(tǒng)默認配置的Buffer數(shù)量*單個buffer的內存大小.目前系統(tǒng)默認BufferQueue中Buffer數(shù)量是3热凹,那么EGL mtrack = 3 * 單個buffer的內存大小泵喘。

還是以com.meizu.safe應用為例,當應用在前臺時般妙,我們查看其數(shù)據(jù):

m17:/ # cat /sys/kernel/debug/ion/clients/32506-0                                                                                                                                     
          buffer             task  pid           thread  tid       size  # procs      flag
------------------------------------------------------------------------------------------
ffffffc00e70d880   surfaceflinger 1069    Binder:1069_4 1241    4153344        1        40
ffffffc02e16b800   surfaceflinger 1069    Binder:1069_4 1241    4153344        1        40
ffffffc06baa3100   surfaceflinger 1069    Binder:1069_2 1075    4153344        1        40
------------------------------------------------------------------------------------------
       heap_name:    size_in_bytes size_in_bytes(pss)
ion_noncontig_he:         12460032           12460032

其中ion_noncontig_he代表這個應用由gralloc分配的內存總和纪铺。

這里有一個要注意的點,按home鍵讓應用退到后臺時碟渺,ion_noncontig_he的值就為0霹陡。這是一個優(yōu)化。


看完單個應用止状,我們再看一下機器整體的數(shù)據(jù):
清空多任務烹棉,解鎖進入桌面:

(1)adb shell dumpsys meminfo查看總共的EGL mtrack數(shù)值。

total = 18380K

(2)adb shell dumpsys meminfo surfaceflinger查看SurfaceFlinger的值

cat對應節(jié)點:

SurfaceFlinger沒有EGL mtrack這項統(tǒng)計
雖然app對應的BufferQueue的GraphicBuffer都是由SurfaceFlinger通過gralloc申請的怯疤,但是在samsung平臺上浆洗,EGL mtrack這部分數(shù)據(jù)并不算在SurfaceFlinger進程。

(3)分別查看system_server集峦、launcher伏社、systemui、recent的數(shù)據(jù)



| PkgName | EGL mtrack |
| ------------- |:-------------:| -----:|
| system_server | 4224 |
| com.android.systemui | 1988 |
| com.meizu.flyme.launcher | 12168 |
| com.android.systemui:recents | 0 |
| total | 18380 |

各個應用EGL mtrack數(shù)據(jù)加起來正好等于總和塔淤。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末摘昌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子高蜂,更是在濱河造成了極大的恐慌聪黎,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件备恤,死亡現(xiàn)場離奇詭異稿饰,居然都是意外死亡,警方通過查閱死者的電腦和手機露泊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進店門喉镰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人惭笑,你說我怎么就攤上這事侣姆∩妫” “怎么了?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵捺宗,是天一觀的道長柱蟀。 經常有香客問我,道長偿凭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任派歌,我火速辦了婚禮弯囊,結果婚禮上,老公的妹妹穿的比我還像新娘胶果。我一直安慰自己匾嘱,他們只是感情好,可當我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布早抠。 她就那樣靜靜地躺著霎烙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蕊连。 梳的紋絲不亂的頭發(fā)上悬垃,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天,我揣著相機與錄音甘苍,去河邊找鬼尝蠕。 笑死,一個胖子當著我的面吹牛载庭,可吹牛的內容都是我干的看彼。 我是一名探鬼主播,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼囚聚,長吁一口氣:“原來是場噩夢啊……” “哼靖榕!你這毒婦竟也來了?” 一聲冷哼從身側響起顽铸,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤茁计,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谓松,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體簸淀,經...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年毒返,在試婚紗的時候發(fā)現(xiàn)自己被綠了租幕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡拧簸,死狀恐怖劲绪,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤贾富,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布歉眷,位于F島的核電站,受9級特大地震影響颤枪,放射性物質發(fā)生泄漏汗捡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一畏纲、第九天 我趴在偏房一處隱蔽的房頂上張望扇住。 院中可真熱鬧,春花似錦盗胀、人聲如沸艘蹋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽女阀。三九已至,卻和暖如春屑迂,著一層夾襖步出監(jiān)牢的瞬間浸策,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工惹盼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留的榛,地道東北人。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓逻锐,卻偏偏與公主長得像夫晌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子昧诱,可洞房花燭夜當晚...
    茶點故事閱讀 43,595評論 2 350