Android内存解析<一>
2017-07-25 18:21
295 查看
Android内存解析<一>
最近有空在家休息,决定乘此机会写写这些年学习中积累的一些知识,算是一个总结,方便后续用到时可以来此翻看。 最近半年都是在与Android平台的Memory打交道,所有就先从Android Memory的部分开始总结。关于Memory我主要从如下两个方面来写:
Android平台Memory分析
Android进程Memory分析
大的方向是两个,Android平台的开发者以及设备厂商们会比较关心整个Android手机整体Memory的使用状况,比如kernel memory的使用、user space memory的使用以及free memory状况等。而App的开发者们一般侧重在对进程Memory的分析,或者更多的是在分析Heap memory的使用。
两个方向的分析过程中会涉及到一些其他的memory知识,比如Java虚拟机的Memory管理、Linux内存管理、C/C++程序的Memory等,这部分在提到时再单独链接相应的文章进来说明。
Android平台Memory分析
Android平台的开发者们在开发一个产品时,针对市场会有不同的定位,对内存的选型也会有差异,例如选用1G、2G、4G的RAM。不同RAM size的产品在Feature上会稍有差别,例如1G的产品会支持更少的Feature, 最高只开HD的屏,不开FHD的屏等等。总的来说对Memory的使用是精打细算,在RAM固定的状况下,既希望提供出更丰富的功能,又希望能省下更多的Free memory保证系统的流畅性,力争用户体验比对手更优。所以对于系统中各个部分Memory的使用状况必须非常清晰,带着这个想法,我尝试把了解到的一些内容记录下来。一、Memory Layout
从整体来看我们可以把Android设备所使用的Memory看成两部分,一部分是预留给其他硬件设备的Memory,一部分是Linux系统可以看到的Memory。1. Hardware reserved memory
给其他硬件设备预留的Memory是Linux系统无法访问到的,这部分主要包含为Modem、Frame buffer、TEE以及WiFi 等chip预留的一些Memory。
那这部分的Memory有多大呢,我们不妨来看看。例如拿我手边2G的设备查看iomem, 可以计算出所有的System RAM为1936M, 则:
HW reserved = RAM Size(2048M) - System RAM(1936M) = 112M
HW Reserved中占比最大的一般是Modem,这部分也与Modem本身支持的模数等都有关系,各Modem厂家本身的代码实现差异也不同,size大小各有差异。
Frame buffer的大小则比较固定,主要由LCM的Resolution决定。
TEE是关于手机安全相关,例如指纹识别等,所以跟支持的功能有强相关。
另外System RAM以及HW reserved memory的计算方法在不同平台上由于有一些客制化,导致可能存在一些差异,这部分我们暂且不表。
2. System RAM
System RAM的部分是主Chip(或者可以叫AP端)可以看到的Memory 。这部分我们也先将其看成两个部分。
2.1. Kernel reserved
第一部分是Kernel reserved memory。主要是Kernel image、 kernel data、用于Linux memory管理的page array以及其他一些杂项。这部分是固定开销,没有办法把Memory再要回来给系统使用。如果想优化成小的size则需要深入kernel。
kernel的大小也可以从iomem中查看到,例如这边看到的kernel code是13M, kernel data是4.5M,Kernel的大小与linux kernel版本相关。
2.2. MemoryTotal
第二部分我这里直接称其为MemoryTotal。这是Linux系统真正能自由分配使用的Memory,也是我们所知的Linux Buddy system按page管理的Memory。MemoryTotal的大小我们可以很方便的查看到,如下我手边的一台2G的设备是1886M:
反推一下,从MemoryTotal我们也可以得到kernel reserved的大小:
kernel reserved = System Ram(1936M) - MemoryTotal(1886M) = 50M
我们已经知道MemoryTotal是Android系统上使用page管理,可以真正使用起来的Memory,那这里面具体又是哪些模块在使用呢?还是使用简单的图形来表示这一块Buddy system所管理的memory区域的组成:
把MemoryTotal分三个部分来看:
2.2.1. kernel used
第一个部分是kernel used, 可以认为是kernel space中的memory用量。列出如下:
从meminfo中可以看到部分kernel memory的使用状况:
对于ION及3D memory,由于基本上是user space的process在使用,只是在kernel space进行了分配管理。所以可以从process的memory分析中去查看这两个部分。
2.2.2. User space memory
第二部分是User space的memory用量,也是我们最为熟悉的所有的进程(包括java层以及native层所有process)的Memory使用量。process的使用状况可以从dumpsys meminfo中获取到,从这个信息中我们可以很清楚的把握到每个process以及所有process的memory的使用状况。如果对于单个process的memory有疑问则可以再使用后续App Memory的分析方法做进一步分析。
把所有process的memory用量进行加总,则是user space中所有process目前memory的使用量。
Process Name | KB | MB |
---|---|---|
system | 84022 | 82.05273438 |
com.android.systemui | 80856 | 78.9609375 |
com.sohu.inputmethod.sogou | 51471 | 50.26464844 |
com.android.settings | 46759 | 45.66308594 |
… | … | … |
Total | 860334 | 840.1699219 |
Total PSS = AnonPages(625408)+ Mapped(193284) = 818692KB.
(这边计算稍有差异是因为抓取memory的时间点有差异)这边采用的计算方法是把所有的process使用的memory分成了两种类型,一种是Anonymous memory,例如stack, heap等,另一种是Mapped Memory, 例如RO code, RO data等。
2.2.3. Free Memory
第三个部分Free是Linux系统尚未分配出去的page Memory,对应meminfo中的MemFree。
二、Cache Free Memory
各平台或设备厂家在开发过程中会不断优化各模块Memory的用量,以期望能塞进更丰富的功能,同时期望为用户留有足够的剩余Memory。如果剩余的Memory过少,意味着可同时运行的App数目会减少,新的App在起来时,需要LMK kill掉其他的process才能获取到足够的Memory,如果想再回到之前的App时,相当于First launch, 必然会影响到performance。所以工程师们会一直关注一个重要的指标:Cache Free。要如何理解cache free呢?我们可以这样来思考,当一个新的App起来的时候,还能要到多少的memory?首先如下三项Memory是可以直接要到的:
1. MemFree
2. Buffers
3. Cached
因此一些初步的Free Memory评估会直接对上面三项Memory加总。
另外还有一部分Background process(Adj >=9),优先级比较低,认为是可以被回收的。这部分Memory可以从adb shell dumpsys meminfo中查看到,例如:
Google在考虑Free memory时,同时还考虑了系统performance问题。由于前面第三项Cached部分还包含了各进程file mapped memory,而回收掉file mapped memory必然会影响process的performance。所以也考虑在计算Cache free时需要减去Mapped memory.
当然,对于Cache free的计算都是估算,系统是复杂的,很难做到精确的计算,而且精确的意义也不大。
在认识到Memory的使用状况以及Cache Free的评价指标后,工程师们要做的就是努力优化各模块的Memory用量。下一篇我会从Process的角度来介绍单个进程中Memory的使用状况,在完整把握Process Memory的前提下能更好的寻求到合理的优化方案。
相关文章推荐
- Android 线程本地变量<一> ThreadLocal源码解析
- Android内存解析<二>
- Android Dalvik虚拟机<一>
- Android 4.2 Input Event事件处理流程<一>事情派发
- 【android自定义控件】TextView详解及自定义<一>
- Unity的Json解析<一>--读取Json文件
- Android JNI/NDK开发之基本姿势<一>
- 使用SimpleXml解析xml数据<一>
- Android Layout研究 <一> 基础知识
- android-文件解析-<八>
- Android <activity-alias> 的用法解析
- cocos2d-x基础<一> Android环境配置和HelloWorld的运行
- Unity的Json解析<一>--读取Json文件
- 强大的Android图片下载缓存库——Picasso<一>
- 【Android:<一>】解决google下载缓慢的问题
- Android游戏开发指南<一>背景地图
- Java/Android 设计模式<一> 单例模式+建造者模式
- <2>Android HAL 发展。文件。两种架构。实例解析
- Android 5.0学习<一>
- Android 新API 之 MediaCodec使用笔记 <一>