免费的行情软件网站下载入口,No餐饮网站建设,制作简单的站点推广方案,ppt之家模板免费下载/proc/meminfo memory状态解读
命令#xff1a;adb shell cat /proc/meminfo内存分布log 查看方式
命令#xff1a;adb shell cat /proc/meminfo
用途:可以整体的了解memory使用情况
我们说的可用memory一般以MemAvailable的数据为准。所以了解MemAvailable的组成可以帮助…/proc/meminfo memory状态解读
命令adb shell cat /proc/meminfo内存分布log 查看方式
命令adb shell cat /proc/meminfo
用途:可以整体的了解memory使用情况
我们说的可用memory一般以MemAvailable的数据为准。所以了解MemAvailable的组成可以帮助理解如何提升可用内存
MemAvailable freefilepage slab_reclaimable -(lowmem_reserve high_wmark_pages) -min(filepage/2,wmark_low) - min(slab_reclaimable/2,wmark_low)
其中:
lowmem_reserve为cat /proc/zoneinfo中的protection数据 一般获取到的数据为0 protection: (0, 0, 0)
high_wmark_pages 和 wmark_low 也是从zoneinfo中获取的high/low 水位
所以上述公式可以理解为 free, filepage, slab_reclaimable越大且high_wmark_pages, wmark_low越小 则MemAvailable越多 Name 释义 Action MemTotal 系统可用的总内存 (MemTotal real_Dram_size - hw_reserved - kernel_reserved ) 若MemTotal未达到预期请查看reserved memory部分check是否可以优化 MemFree 当前剩余的物理内存总量 free跟process数据有关就算有被压缩但其还是会mapping相关的memory造成free比较少 如果cachedMemFree 200M可能就会出现memory使用紧张的问题 MemAvailable 系统可用内存 , 包含已使用但可回收的 , 如available freefilepage slab_reclaimable -(lowmem_reserve high_wmark_pages) -min(filepage/2,wmark_low) - min(slab_reclaimable/2,wmark_low) 参见code si_mem_available 其中lowmem_reserve为/proc/zoneinfo中的protection信息。 1、如果刚开机未达到开机可用内存目标请查看开机memory数据获取按照要求进行获取数据,然后再按照如下几个步骤进行check; 1.1、check 本表格中MemTotal 是否达到预期 1.2、check 本表格中anonfile的用量比 1.3、check kernel memory分解, 排查kernel使用异常部分并优化 1.4、check dumpsys meminfo分解 排查某个或某些内存占高的进程并优化 2、若是运行过程中出现low memory 问题 则可以从降低单个process的memory使用量以及减少后台process的存活数量来着手加强后台管理。具体请参考Low memory 处理建议。 Buffers Buffer是为了cpu和块设备block device之间读写速度不对等而设计的Buffers统计的就是这部分缓冲区的内存总大小。这部分内存drop cache可以被回收。 Cached 用于文件高速缓存不包括swapcache和buffers 即Cached file pages-swapcache-buffers 约等于 Active(file) Inactive(file) cached统计了文件的缓存其中有些文件当前被unmap, cache仍然可能保留它们该部分可以被drop cache直接回收而还有一部分被用户进程关联比如shared libraries,mmap的文件等这些缓存也就称为mapped. mapped是包含在cached里面这部分是不可以被drop caches的. cached都是file page,不是anon page, cached 和anon page之间没有重叠。 cached的大小一定程度上决定了MemAvailable的大小。所以若cached太小请check anonpage和file page的比例 SwapCached 缓存的会swap出去的内容 Active 活跃的file page和匿名page Active Active(anon) Active(file) 记录最近使用过的内存通常不回收用于其它目的 Inactive 非活动的file page和匿名page Inactive Inactive(anon) Inactive(file) 记录最近并没有使用过的内存能够被回收用于其他目的 Active(anon) 活跃的匿名页 如果anon数据较多而file文件较少请继续check swap Total和 SwapFree两个参数 Inactive(anon) 不活跃的匿名页 Active(file) 活跃的文件页 Inactive(file) 已经使用的不活跃的文件页 Unevictable 已经使用的不可回收的页. 包括VM_LOCKED的内存页、SHM_LOCK的共享内存页又被统计在”mlocked”中、和ramfs。 Mlocked 通过mlock锁定在内存中当中的空间不会被放到swap space当中 SwapTotal swap分区的总量 1、针对低端机可以适当加大swaptotal如2G RAM 可以将其设置到1.3G左右 2、如果swapFree还剩余很多且anon数据量大请查看swappiness 的设置并加大其设定的参数 adb shell cat /proc/sys/vm/swappiness 3、如果swapFree已经所剩无几说明当前process较多或者process所占内存较大。如果当前已处于低内存状态请查看dumpsys meminfo分解 排查某个或某些内存占高的进程并优化 关于swap详细介绍请参考zram swap swappiness SwapFree swap分区目前可用的量 Dirty 脏页的数量就是文件内容有改变的页 在磁盘缓冲区中尚未写入物理磁盘的内存大小 Writeback 要被回写的内存页的大小 AnonPages 未映射文件的内存页数量 Linux内核中存在一个rmap(reverse mapping)机制负责管理匿名内存中每一个物理内存页映射到哪个进程的哪个逻辑地址这样的信息。 这个rmap中记录的内存页总和就是AnonPages的值 Mapped 文件通过mmap分配的内存用于map设备、文件或者库 Shmem 被各个进程共享的内存页的数量 tmpfs所使用的内存.tmpfs即利用物理内存来提供RAM磁盘的功能。在tmpfs上保存文件时文件系统会暂时将它们保存到磁盘高速缓存上因此它是属于磁盘高速缓存对应的bufferscached一类。。但是由于磁盘上并没有与之对应的内容因此它并未记录在File-backed内存对应的LRU列表上而是记录在匿名内存的LRU表上。 这就是 buffers cached Active(file) Inactive(file) Shmem 公式的由来 被统计如kernel 占用内存详见kernel memory分解 Slab kernel数据结构的缓存大小SlabSReclaimableSUnreclaim Slab allocator是Linux kernel的内存分配机制各内核子系统、模块、驱动程序都可以使用但用完应该记得释放忘记释放就会造成“内存泄露”(memory leak)。如果导致泄露的代码使用率很低倒也罢了若是使用率很高的话系统的内存会被迅速耗尽。 SReclaimable Slab可被回收的量。 调用kmem_getpages()时加上SLAB_RECLAIM_ACCOUNT标记表明是可回收的计入SReclaimable否则计入SUnreclaim。 SUnreclaim Slab中不可回收的量 KernelStack 内核线程栈占用的空间 PageTables 该进程页表所占用的memory NFS_Unstable 不稳定页表的大小 Bounce 有些老设备只能访问低端内存比如16M以下的内存当应用程序发出一个I/O 请求DMA的目的地址却是高端内存时比如在16M以上内核将在低端内存中分配一个临时buffer作为跳转把位于高端内存的缓存数据复制到此处。这种额外的数据拷贝被称为”bounce buffering”会降低I/O 性能。大量分配的bounce buffers 也会占用额外的内存。 WritebackTmp CommitLimit 指当前可以分配给程序使用的虚拟内存 Committed_AS 指当前已分配给程序使用的总虚拟内存 VmallocTotal 总分配的虚拟地址空间 VmallocUsed vmalloc已经使用的内存量 VmallocChunk 当前剩余的最大连续空间的大小 内存分布log 查看方式
kernel log
4[366310.867958] DMA free:68160kB min:5140kB low:44156kB high:45996kB active_anon:126592kB inactive_anon:126772kB active_file:211508kB inactive_file:185592kB unevictable:5380kB writepending:1896kB present:1988536kB managed:1841596kB mlocked:5380kB slab_reclaimable:40648kB slab_unreclaimable:187980kB kernel_stack:49760kB pagetables:78368kB bounce:0kB free_pcp:2844kB local_pcp:696kB free_cma:0kB
DMA free:68160kB 总剩余内存min:5140kB low:44156kB high:45996kB min/low/high 三个水位值其释义可以参考Linux内存调节之zone watermarkactive_anon:126592kB inactive_anon:126772kB userspace process memoryactive_file:211508kB inactive_file:185592kB userspace file cache memorymanaged:1841596kB DRAM total减掉 reserved memory 系统总共可运用的内存大小slab_reclaimable:40648kB slab_unreclaimable:187980kB slab 占用内存kernel_stack:49760kB kernel stack 占用内存 可用来计算process数量 32bit 8k per process , 64bit 16k per porcess注意ion 和 gpu 无法由此看出, 可以通过dumpsys meminfo分解 部分进一步确认 dumpsys meminfo分解
1、指令 dumpsys meminfo 2、dumpsys meminfo $pid
1、指令 dumpsys meminfo
描述可以了解系统详细的memory使用的情况通过dumpsys meminfo 可以得到系统中各个process占用的内存情况各种adj情况下的process的内存分布总体的memory的使用统计等信息。区别于/proc/meminfo提供的内存数据dumpsys meminfo更加偏向于andorid系统对于系统中memory使用情况的理解因此我们在实际的memory的debug的过程中在android系统会倾向使用dumpsys meminfo
执行结果 名称 计算方式 next action Total PSS by process 将系统中run的process的内存信息打印出来通过该部分信息可以清楚的看到每个process的内存使用情况 在实际debug的过程中我们的如果怀疑某个process内存使用异常或者有leak的嫌疑我们会以这个里面提供该process为基准进行相应的判断。。如果某个process的memory占用过大或者一直增长则可以通过dumpsys meminfo pid 来进一步check. Total PSS by OOM adjustment andorid系统的继承了部分linux 内存管理的做法会在系统内存比较紧张或者在某些内存长期不使用的情况会清掉优先级较低的进程来让系统的具有良好的内存使用状况。对android系统我们的会对每个process进行打分分数越高表示优先级越低在内存紧张的时候就越容易被回收。 1native process native process的优先级一般很高都是在0以下内存很难被回收 2Foreground 表示前台进程优先级为0 3Cached表示adj900 的进程优先级比较低在系统内存紧张的时候可以随时被回收 在实际debug的过程中我时常会遇到系统因为memory紧张导致重启的case这种情况大都是native process 或者kernel里面有leak导致的。kernel 里面的leak大都是driver不合理的memory 使用导致的可以使用page owner来抓判断native的process是否有leak就是可以根据上述的native process里面是否有使用内存异常的process来判断。 total PSS cached pss used pss (cached pss : adj 900 process pss sum , used pss : adj 900 process pss sum) 检查是否有占用memory异常多的process然后再根据本文第二部分的dumpsys meminfo $pid的内容进一步确认单个process memory 占用异常的问题 total kernel cached kernel kernel 确认kernel部分的占用情况 cached kernel slab reclaimable buffers cached - mapped kernel slab unreclaimable shmem vmalloc page tables kernel stack 参见kernel memory分解 EGL/GL ION/GPU内存占用可参考本文第二部分的dumpsys meminfo $pid 中graphics部分 ION部分请参考ION GPU部分请参考 FAQ22281 [Memory]如何查看gpu memory 讯息 2、dumpsys meminfo $pid 名称 计算方式 如果相应值偏大next Action: code .so private (cleandirty) .jar private (cleandirty) .apk private (cleandirty) .ttf private (clean dirty) .dex private (clean dirty) .oat private (clean dirty) 1、参考dumpsys 上面各个组成部分定位是哪部分数据过大:.so/.jar/.apk/.ttf/.dex/.oat? 2、参考maps/smaps/showmap使用showmap/smaps再具体定位是哪个文件然后再请相应owner进一步确认或优化 Java heap Dalvik private dirty.art mmap private clean.art mmap private dirty 抓取hprof 排查 heap 分布 (参考FAQ08893 如何抓取app 进程的hprof) graphics GL mtrack private (clean dirty) EGL mtrack private(clean dirty) FAQ22290 [Memory]如何查看ion memory usage FAQ22281 [Memory]如何查看gpu memory 讯息 Quick Start 内存泄漏专题分析 native内存泄漏 ion内存泄漏 native heap native private dirty Quick Start 内存泄漏专题分析 native内存泄漏 或参考 /development/scripts/native_heapdump_viewer.py 使用malloc debug adb shell am dumpheap $pid 查看 具体参见后面介绍 private other private clean列private dirty列-java heap-native heap-code-stack-graphic PSS total Pss Total列总和 SwapPss Dirty列总和 stack stack private dirty system total-private Clean 列总和private dirty列总和
其中 .so,.jar,.apk,.ttf,.dex,.odex,.vdex,.oat,.art都是is_swappable的其函数实现可参考
/frameworks/base/core/jni/android_os_Debug.cpp function load_maps Pss、Shared Dirty、Private Dirty这三列的数据是读取smaps文件生成。
下载 native_heapdump_viewer.py /development/scripts/native_heapdump_viewer.py 介绍 30 1. Collect a native heap dump from the device. For example: 31 $ adb shell stop 32 $ adb shell setprop libc.debug.malloc.program app_process 33 $ adb shell setprop libc.debug.malloc.options backtrace64 34 $ adb shell start (launch and use app) 36 $ adb shell am dumpheap -n pid /data/local/tmp/native_heap.txt 37 $ adb pull /data/local/tmp/native_heap.txt 38 39 2. Run the viewer: 40 $ python native_heapdump_viewer.py [options] native_heap.txt 41 [--verbose]: verbose output 42 [--html]: interactive html output 43 [--reverse]: reverse the backtraces (start the tree from the leaves) 44 [--symbols SYMBOL_DIR] SYMBOL_DIR is the directory containing the .so files with symbols. 45 Defaults to $ANDROID_PRODUCT_OUT/symbols 46 [--app-symbols SYMBOL_DIR] SYMBOL_DIR is the directory containing the app APK and so files. 47 Defaults to the current directory. 48 This outputs a file with lines of the form: 49 50 5831776 29.09% 100.00% 10532 71b07bc0b0 /system/lib64/libandroid_runtime.soTypeface_createFromArray frameworks/base/core/jni/android/graphics/Typeface.cpp:68 51 52 5831776 is the total number of bytes allocated at this stack frame, which 53 is 29.09% of the total number of bytes allocated and 100.00% of the parent 54 frames bytes allocated. 10532 is the total number of allocations at this 55 stack frame. 71b07bc0b0 is the address of the stack frame. maps/smaps/showmap
1、maps2、smaps3、showmap
Linux采用虚拟内存技术管理process 地址空间. 将process memory分成不同的内存区。每个区域具有各自的访问属性大小是4k的倍数。
代码实现上使用vm_area_struct节点串成链表。 我们可以从maps smaps里面获取到process detail的memory信息。
参考link: kernel document https://www.kernel.org/doc/Documentation/filesystems/proc.txt 1、maps
adb shell cat /proc/pid/maps
77bed25000-77bed26000 rw-p 00013000 fd:04 1434 /vendor/lib64/libgpu_aux.so
该文件有6列:
地址(77bed25000-77bed26000)地址范围
权限(rw-p)虚拟内存的权限r读w写,x执行,s共享,p私有
偏移量(00013000)在进程里地址偏移量
设备(fd:04)映像文件的主设备号和次设备号可以通过通过 cat /proc/devices查看设备号对应的设备名
节点(1434)映像文件的节点号
路径(/vendor/lib64/libgpu_aux.so): 映像文件的路径
每项都与一个vm_area_struct结构成员对应。 2、smaps
adb shell cat /proc/pid/smaps
smaps是对maps 信息的详细描述。描述了每个虚拟内存区域的size等信息。
00400000-0048a000 r-xp 00000000 fd:03 960637 /bin/bash // 该行同maps中的信息 Size: 552 kB //指vss 以及后面RSS PSS释义请参见procrank 分解及VSS/RSS/PSS/USS基础知识 Rss: 460 kB Pss: 100 kB Shared_Clean: 452 kB //映射中已被此进程引用的页面,以及至少一个其他进程,但不是由任何进程编写的;Shared_Dirty: 0 kB //映射中已被此进程引用的页面,并且至少由其中一个进程编写; 其中dirty页如果没有交换机制的情况下应该是不能回收的Private_Clean: 8 kB //映射中已读取但未由此进程写入但未被任何其他进程引用的页面;Private_Dirty: 0 kB //映射中已由此进程写入但未被任何其他进程引用的页面. Referenced: 460 kB //表示当前标记为已引用或者已访问的内存量 Anonymous: 0 kB //不属于任何文件的内存量 AnonHugePages: 0 kB ShmemHugePages: 0 kB ShmemPmdMapped: 0 kB Swap: 0 kB //显示多少潜在的已经被使用但没有被交换的匿名内存内存页 KernelPageSize: 4 kB //kernel用来支持虚拟内存区域的页面大小。一般与MMU使用大小相匹配。 MMUPageSize: 4 kB //被MMU使用的页面大小 Locked: 0 kB //表示映射是否被锁定在内存中 ProtectionKey: 0 VmFlags: rd ex mr mw me dw
根据smaps中每一项的object内容可以把memory分成不同的category借助其他统计工具可以统计出每种类型Memory的用量。 .so cmdline: contains .so native lib. RO RW boot.oat boot.art cmdline: contains .oat or contains .art preloaded classes which are commonly used by multiple apps, 例如core-libart.jar, conscrypt.jar, okhttp.jar, core-junit.jar, bouncycastle.jar, ext.jar, framework.jar telephony-common.jar, android.policy.jar, apache-xml.jar dex cmdline: contains dex Process本身依赖的一些java模块对应的dex Native (Heap) cmdline: contains heap, contains libc_malloc, contains linker_alloc, or contains sigpage stack cmdline: contains stack and does not contain anon anon cmdline: contains anon unknown Java cmdline: contains dalvik Java Heap. 由App本身需要的Heap以及Zygote所占用的Heap两部分组成。 Others perm: contains w or contains x copy-on-write mapping perm: ---p Resource 其他不知如何归类的认为是resource. 例如font, apk等 3、showmap
adb shell system/bin/showmap $pid
功能可以用来定位占用memory比较大的资源模块。定位后可以根据实际情况找相关模块确认是否合理。
virtual shared shared private private size RSS PSS clean dirty clean dirty swap swapPSS # object -------- -------- -------- -------- -------- -------- -------- -------- -------- ---- ------------------------------ 128 4 0 0 4 0 0 0 0 1 /dev/__properties__/properties_serial 152 152 0 0 152 0 0 0 0 2 /dev/__properties__/property_info 128 4 2 0 4 0 0 0 0 1 /dev/__properties__/u:object_r:apexd_prop:s0
我们一般用PSSSwapPss来的求和来计算该文件占用的memory大小。
showmap和smaps的关系
实际是读取上述smaps中的数据然后规整分类,测试中showmap和cat/proc/PID/smaps抓取要连续间隔久了memory会有变化
showmap中看到的是smaps中对应binary r--p/--xp/rw-p/rw-p所有项的聚合是share lib size or execuatable size; smaps中--xp是code size 其他项都是data size procrank 分解及VSS/RSS/PSS/USS基础知识
1、指令 procrank2、VSS/RSS/PSS/USS基础知识 2.1 VSS Process 虚拟地址空间处理2.2 RSS2.3 PSS2.4 USS2.5 图示2.6 番外篇3、swap/PSwap/USwap/ZSwap
1、指令 procrank
功能 获取所有进程的内存使用的排行榜排行是以Pss的大小而排序。 procrank命令比dumpsys meminfo命令能输出更详细的VSS/RSS/PSS/USS内存指标。 其数据是从proc/[pid]/smaps中统计出来的
注意 该指令使用前需先 root
执行结果
k69v1_64:/ # procrank PID Vss Rss Pss Uss Swap PSwap USwap ZSwap cmdline 1163 8301540K 292500K 134167K 115232K 18032K 5372K 1228K 1226K system_server 2036 6239616K 238808K 94109K 45468K 8452K 1935K 596K 441K com.google.android.gms.persistent 2447 6299948K 222520K 80168K 31768K 24008K 8400K 2164K 1917K com.google.android.gms 5548 6612676K 223860K 79406K 53324K 20948K 8504K 3376K 1941K com.google.android.googlequicksearchbox search 7372 5935688K 196336K 71705K 60224K 3824K 86K 0K 19K com.android.settings 1320 6915696K 212372K 66895K 54108K 20620K 7813K 2868K 1783K com.android.systemui 1748 5705716K 162736K 62378K 54820K 0K 0K 0K 0K com.google.android.inputmethod.latin .......
------ ------ ------ ------ ------ ------ ------ 1329992K 906904K 427204K 87374K 19184K 19948K TOTAL
ZRAM: 71488K physical used for 313192K in swap (2157132K total swap) RAM: 3923480K total, 733604K free, 63408K buffers, 1929524K cached, 3792K shmem, 172472K slab 2、VSS/RSS/PSS/USS基础知识
process memory 占用量 2.1 VSS
也写做VIRT或VSZ它是进程使用的虚拟内存总量不管是否有映射了物理内存。VSS在确认单个进程实际内存使用大小过程中用处不大。
比如malloc 一块大内存实际上只分配了虚拟地址并没有映射消耗物理地址只有对这块内存访问时(比如 memeset)才会去映射物理内存。 Vss会高估实际内存使用量因为程序通常会分配一些内存但可能从来没用过。
Process 虚拟地址空间处理 当Process通过exec()类系统调用开始某个Program的执行时Kernel 分配给Process的虚拟地址空间由以下内存区组成
program的可执行代码program的初始化数据program的未初始化数据初始程序stack共享库的可执行代码和数据heap
Kernel采用请求调页(demand paging)的内存分配策略。process可以在它的页还没在内存时就开始执行. 当process 访问一个不存在的页时MMU产生一个异常异常处理程序找到受影响的内存区分配一个空闲的页并用适当的数据进行初始化。 同样process调用malloc 动态请求内存时内核仅修改进程的堆内存区的大小。只有试图引用process的虚拟地址而产生异常时才给进程分配页框。
2.2 RSS
也写作RES或者RSS, 这个是进程映射的物理内存数量。 用Rss来计算程序内存使用量可能稍微好些但是还是会有高估因为它没有考虑到进程间共享的内存。 比如libc.so 在系统中只有一份内存copy但是每个进程的Rss 都会把libc.so link到各进程的空间计算在内。
2.3 PSS
Pss 中除了独享的内存外还会加上平均共享内存共享的内存 除以 共享的进程数量所以是平均值也并不精确占用多少跟共享内存大小及共享进程的数量有关
PSS 是一个非常有用的数字因为系统中全部进程以整体的方式被统计 对于系统中的整体内存使用是一个很好的描述。 如果一个进程被终止 其PSS 中所使用的共享库大小将会重新按比例分配给剩下的仍在运行并且仍在使用该共享库的进程。 此种计算方式有轻微的误差因为当某个进程中止的时候PSS没有精确的表示被返还给整个系统的内存大小。
2.4 USS
Uss只统计进程的独享内存 不包含与其他进程共享的内存。 比如A 和 B 进程都link 了libc.so 那么A 或B进程统计Uss时将把libc.so 占用的内存去掉。
Uss是一个非常非常有用的数据因为它揭示了运行一个特定进程的真实内存增量大小
如果进程被终止USS就是实际被返还给系统的内存大小。
USS是针对某个进程开始有可疑内存泄露的情况进行检测的最佳数据。
2.5 图示
我们假如进程的内存包括
A 映射到物理内存的共享内存这个会包含部分active的stack空间和heap空间。B 进程间映射和共享空间比如shared librariesC 分配但是从未touch的虚拟地址空间。
那么对于每个Process Vss A B C Rss A B Uss A Pss A B/n , n是共享这个内存的Process的数量 假如系统中有如下3个process使用内存如下 Pss(1) 2 3/3 2/2 4 Pss(2) 2 3/3 2/2 4 Pss(3) 2 3/3 3 Sum(Pss) 11 系统所有进程实际使用的物理内存 2.6 番外篇
shared total Tshare Rss - Uss
share memory average Ashare Pss- Uss
通过上述数据可以获得该shared memory 区域的进程数 Nprocess Tshare/Ashare
3、swap/PSwap/USwap/ZSwap zram 信息详见swap swappiness一节。
swap, 表示总共交换出去的size和Rss相对应基本上不看用处不大PSwap, pss中交换出去的size和pss相对应比例分配共享库占用的内存。USwap, 对应Uss进程独自占用的物理内存中交换出去的size。ZSwap, 使用zram 使用的大小。 reserved memory
获取reserved memory的方式 1、 P版本或之前2、 Q版本及以上相关code:优化方式
MemTotal DRAM_Size - Reserved memory.
Reserved memory HW reserved Kernel reserved 获取reserved memory的方式
1、P版本或之前
指令 adb shell cat /proc/mtk_memcfg/total_reserve adb shell cat /proc/mtk_memcfg/reserve_memory
示例 kxxx_64_bsp:/ # cat /proc/mtk_memcfg/total_reserve 230084 kB kxxx_64_bsp:/ # cat /proc/mtk_memcfg/reserve_memory *mblock-15-ccci: 77856768 mblock-9-dtb_kernel_addr_mb: 524288 ram_console-reserved-memory47c80000: 65536 pstore-reserved-memory47c90000: 917504 minirdump-reserved-memory47d70000: 65536 *mblock-4-atf-reserved: 327680 mblock-7-pl-bootarg: 2097152 *mblock-8-lk_addr_mb: 4194304 *mblock-12-SPM-reserved: 65536 *mblock-16-ccci: 23068672 *mblock-14-ccci: 1507328 *mblock-10-framebuffer: 14942208 *mblock-6-SSPM-reserved: 786432 mblock-3-log_store: 262144 *reserve-memory-scp_share: 3145728 *reserve-memory-sspm_share: 5308416 *mblock-13-SCP-reserved: 6291456 *consys-reserve-memory: 4194304 *wifi-reserve-memory: 3145728 *mblock-11-atf-ramdump-memory: 524288 *mblock-5-atf-log-reserved: 262144 *mblock-1-dramc-rk0: 4096 *mblock-2-dramc-rk1: 4096 kernel(text): 14088192 kernel(data): 13785684 kernel(page): 50331584 kernel(other): 7839212
2、 Q版本及以上 2.1 HW reserved memory 使用tool: memory-layout-parser tool (request tool by e-service)
output in excel format SUMMARY Type Size (KB) ccci 95872 md_smem 24576 scp 19456 framebuffer 14464 sspm 5952 consys 4096 lk 4096 wifi 3072 pl 2048 atf 1152 pstore 896 dtb 512 log_store 256 minirdump 64 ram_console 64 spm 64 ion 16 dram 4 Total 176660
HW reserved的优化可以比较测试机和对比机的各个部分的差异以Q平台为例 HW reserved Type phone-A Size (KB) Phone-B Size (KB) diff(B-A) atf 832 1088 256 ccci 67392 77632 10240 consys 4096 4096 0 dram 8 4 -4 dtb 512 512 0 framebuffer 16000 16320 320 lk 4096 9216 5120 log_store 256 256 0 md_smem 1472 1472 0 minirdump 64 64 0 pl 2048 2048 0 pstore 896 896 0 ram_console 64 64 0 scp 4608 9216 4608 sspm 1856 5952 4096 spm 64 64 0 tee 51456 51200 -256 wifi 3072 3072 0 unknown type 0 total 155.07 178.88 23.81
比较后可以根据如下HW reserved表格中方案按实际情况和需求修改对应的偏差较大的部分: HW reserved memory 大小 修改方案 ccci 关闭ccb buffer 将ccb buffer设置成12M 因设置成0M会导致Meta连接不上的问题 10M MTK_DYNAMIC_CCB_BUFFER_GEAR_ID Option Value CCB Size Comments 1 22MB 2 12MB 推荐选择这个 3 0MB 这个即为关闭CCB,但是会有meta连不上的问题 11 4MB 只改project config有可能不生效需要具体再看。 关闭dfd 8M -MTK_DFD_ENABLE_CACHE_DUMP : yes MTK_DFD_ENABLE_CACHE_DUMP : no amms_pos_size 7.5M CMA free 可以被其它user使用不做修改 CCCI_SMEM_SIZE_UDC_NONCACHE 7.44M CMCC需求的3GPP feature. 内部测试机默认R3而客户开案是在LR12A.R2.TC16.Q.SP該Branch並沒有UDC 关闭C2K(CDMA2000) 7MB 申请modem patch参考CR ALPS05131754 IMS:support 40 dialog -10 dialog 4M 申请modem patch参考CR ALPS05131754 需确认modem版本如Gen93 IMS_GEN_CFG GEN93_ENG_SLIM (for LL) IMS_GEN_CFG GEN93_ENG_SLIM_NO_MIMS (for LW) MULTIPLE_IMS_SUPPORT FALSE (for LW) SCP 修改scp_share 10M reserve-memory-scp_share { compatible mediatek,reserve-memory-scp_share; no-map; - size 0 0x00d00000; size 0 0x00300000; alignment 0 0x1000000; alloc-ranges 0 0x40000000 0 0x50000000; }; scp 0.5M slim SCP.rar diff文件的修改Q版本一般都已经包含就只差一个 MTK_MINIMUM_SCP_DRAM_SIZE yes 的配置。但不排除客户有自己的修改。 MTK_MINIMUM_SCP_DRAM_SIZE yes at vendor/mediatek/proprietary/bootable/bootloader/lk/) sspm Using dynamic allocate memory for MET 4M slim SSPM.diff.zip framebuffer Framebuffer的size与LCM 的width/height有关 1、如phone-B用的是1080*1920的LCM, Phone-A用的是720*1080的LCM. 2、这个size还包含Assert layer 贵司可以根据项目的LCM的size自定义framebuffer的大小。 另外非DRM chip 不需要优化因为framebuffer进入kernel之后将转换成FB heap,给Gralloc使用所以不算浪费。
2.2 kernel reserved memory:
进入linux服务区在build 的load路径下out\target\product\[project_name]\obj\KERNEL_OBJ下找到vmlinux 文件,然后在该路径下执行指令 nm vmlinux |grep -e _etext -e _stext -e _edata -e \b_sdata -e __end_rodata -e __start_rodata -e __bss_stop -e __bss_start -e __init_end -e __init_begin -e _einittext -e _sinittext | perl -e while (){ chomp($_); if ($_ ~ /([a-f0-9]) . _etext/) { $_etext $1} elsif ($_ ~ /([a-f0-9]) . _stext/) { $_stext $1} elsif ($_ ~ /([a-f0-9]) . _edata/) { $_edata $1} elsif ($_ ~ /([a-f0-9]) . _sdata/) { $_sdata $1} elsif ($_ ~ /([a-f0-9]) . __end_rodata/) { $__end_rodata $1} elsif ($_ ~ /([a-f0-9]) . __start_rodata/) { $__start_rodata $1} elsif ($_ ~ /([a-f0-9]) . __bss_stop/) { $__bss_stop $1} elsif ($_ ~ /([a-f0-9]) . __bss_start/) { $__bss_start $1} elsif ($_ ~ /([a-f0-9]) . __init_end/) { $__init_end $1} elsif ($_ ~ /([a-f0-9]) . __init_begin/) { $__init_begin $1} elsif ($_ ~ /([a-f0-9]) . _einittext/) { $_einittext $1} elsif ($_ ~ /([a-f0-9]) . _sinittext/) { $_sinittext $1}} $codesize hex($_etext) - hex($_stext); print codesize .int($codesize/1024) . K\n; $datasize hex($_edata) - hex($_sdata); print datasize .int($datasize/1024) .K\n; $rosize hex($__end_rodata) - hex($__start_rodata); print rosize .int($rosize/1024) . K\n; $bss_size hex($__bss_stop) - hex($__bss_start); print bss .int($bss_size/1024) . K\n; $init_data_size hex($__init_end) - hex($__init_begin); print init_data_size .int($init_data_size/1024) .K\n; $init_code_size hex($_einittext) - hex($_sinittext); print init_code_size .int($init_code_size/1024) .K\n 得到的结果 codesize14526K datasize1986K rosize4972K bss2733K init_data_size3904K init_code_size455K kernel(text) codesize kernel(data) datasizerosizebss kernel(init) init_data_size
跟kernel log中dump是一致的,所以获取Kernel reserved memeory的状况二选一就好
Memory: 1726420K/2056764K available (14526K kernel code, 1986K rwdata, 4972K rodata, 3904K init, 2733K bss, 330344K reserved, 0K cma-reserved)
相关code:
How to reserved memory
---use mblock_reserve or mblok_reserve_ext in lk
ex: /vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6755/ A D platform.c 546 addr mblock_reserve(g_boot_arg-mblock_info, 0x2100000, 0x100000, 0xa0000000, RANKMAX); in mblock_create_test() 671 g_fb_base mblock_reserve(g_boot_arg-mblock_info, g_fb_size, 0x200000, 0x100000000, RANKMAX); in platform_init() 674 g_fb_base mblock_reserve(g_boot_arg-mblock_info, g_fb_size, 0x100000, 0x100000000, RANKMAX); in platform_init() 2. dts config
ex:
242 reserved_memory: reserved-memory {
243 #address-cells 2;
244 #size-cells 2;
245 ranges;
246
247 reserve-memory-sspm_share {
248 compatible mediatek,reserve-memory-sspm_share;
249 no-map;
250 status okay;
251 #ifdef CONFIG_MTK_GMO_RAM_OPTIMIZE
252 size 0 0x110000; /* 1M 64K */
253 #else
254 size 0 0x510000; /* 5M 64K */
255 #endif
256 alignment 0 0x10000;
257 alloc-ranges 0 0x40000000 0 0x60000000;
258 };
259
260 reserve-memory-scp_share {
261 compatible mediatek,reserve-memory-scp_share;
262 no-map;
263 size 0 0x00300000;
264 alignment 0 0x1000000;
265 alloc-ranges 0 0x40000000 0 0x50000000;
266 };
267
268 consys-reserve-memory {
269 compatible mediatek,consys-reserve-memory;
270 no-map;
271 size 0 0x400000;
272 alignment 0 0x1000000;
273 alloc-ranges 0 0x40000000 0 0x80000000;
274 };
275
276 wifi-reserve-memory {
277 compatible mediatek,wifi-reserve-memory;
278 no-map;
279 size 0 0x300000;
280 alignment 0 0x1000000;
281 alloc-ranges 0 0x40000000 0 0x80000000;
282 }; 优化方式
1 其他feature需相应owner来一一check优化对比
2 MD需MD PL列出相应的featurePM根据市场需求来决定开启/关闭哪些feature如前文中Hw reserved表格中所列优化项。以达到优化的目的
3 kernel code/data相关的部分 3.1 先从 linux/bloat-o-meter at master · torvalds/linux · GitHub 获取最新的bloat-o-meter script 3.2 Comparing code/data/bss size of vmlinux by bloat-o-meter
Linux provides a script to compare two vmlinux and generates report for them.
Usage: latest bloat-o-meter has options such as -t (text), -d (data), and -c (categorized output).
./script/bloat-o-meter vmlinux-old vmlinux-new
output of report
add/remove: 2062/1304 grow/shrink: 23801/2790 up/down: 2133305/-367564 (1765741)
Function old new delta
RGXDumpRGXRegisters - 18196 18196
musb_ep_program - 12740 12740
uvc_probe - 8648 8648
v4l2_ctrl_get_name - 7008 7008
update_blocked_averages 2088 8820 6732
ISP_Buf_CTRL_FUNC 9732 15888 6156
...
Total: Before11226411, After12992152, chg 15.73%kernel memory分解
kernel total MEMINFO_SHMEMMEMINFO_SLABMEMINFO_VM_ALLOC_USEDMEMINFO_PAGE_TABLESMEMINFO_KERNEL_STACK Kernel 备注 MEMINFO_SHMEM Shmem统计的内容包括 · shared memory: · SysV shared memory [shmget etc.] · POSIX shared memory [shm_open etc.] · shared anonymous mmap [ mmap(…MAP_ANONYMOUS|MAP_SHARED…)] · tmpfs和devtmpfs。 注所有tmpfs类型的文件系统占用的空间都计入共享内存devtmpfs是/dev文件系统的类型/dev/下所有的文件占用的空间也属于共享内存。可以用ls和du命令查看。如果文件在没有关闭的情况下被删除空间仍然不会释放shmem不会减小 MEMINFO_SLAB 同process 数量有关,则可考虑减少process or task · FAQ21613 [Memory]如何分析slab占用内存细节以及slab leak · FAQ21615 [Memory]如何查询内核所有 page 的使用情况 (by page owner) MEMINFO_VM_ALLOC_USED (All size in adb shell cat /proc/vmallocinfo exclude lines with ioremap / map_lowmem / vm_map_ram / “unpurged”pattern) 最新结果表明kernel-4.14上 unpurged 也是可用部分所以也应在计算时去除 MEMINFO_PAGE_TABLES 用于将内存的虚拟地址翻译成物理地址。随着内存地址分配的越来越多page table 会增大。 Page Table的用途是翻译虚拟地址和物理地址它是会动态变化的要从MemTotal中消耗内存 同process or task 数量有关, 数据太大则可考虑减少process or task MEMINFO_KERNEL_STACK 每一个用户线程都会分配一个kernel stack内核栈内核栈虽然属于线程但用户态的代码不能访问只有通过系统调用(syscall)、自陷(trap)或异常(exception)进入内核态的时候才会用到也就是说内核栈是给kernel code使用的。 Kernel stack内核栈是常驻内存的既不包括在LRU lists里也不包括在进程的RSS/PSS内存里。所以属于kernel消耗的内存。
上面的数据除MEMINFO_VM_ALLOC_USED外其它几项都来自于adb shell cat /proc/meminfo。所以本部分主要介绍MEMINFO_VM_ALLOC_USED的计算
1、adb shell cat /proc/vmallocinfo SYS_VMALLOC_INFO
2、用TextAnalysisTool.NET工具打开获取到的SYS_VMALLOC_INFO 文件然后按“ctrlN”键去除显示ioremap / map_lowmem / vm_map_ram / “unpurged”几个关键字 3、然后将剩下的内容全部copy到excel中然后点选 数据→分列-选择分隔符号-勾选空格”和“其他:”-完成 4、统计所有function size的大小之和如下图所示
先在首行插入一行填写每列所代表的释义选取 D列和E列(size 大小列和function name 列)-插入-数据透视表-选择防止数据透视表位置-现有工作表然后任意选择空白区域→确定 在右边的数据透视表字段中勾选size到值勾选function到行然后在左边的数据表格中双击求和项选择求和。就可以显示每个function用掉的memory size了。
5、获得各个function size后选出使用量最大的进行分析请相关owner确认是否有使用异常或者是否可以瘦身。
番外篇关于kernel-4.9 vs kernel-4.14 vmalloc usage Row Labels kernel-4.9 sum of size(KB) kernel-4.14 Sum of sizeKB diff (KB) 备注 _do_fork 0 53180 53180 kernel-4.14有开启CONFIG_VMAP_STACK 这个功能会把thread alloc计算到vmalloc中该功能请参考 Several ARM64 Changes Queued For Linux 4.14, VMAP_STACK Support - Phoronix 基本上是多一个 stack overflow 的debug机制。 如不需要则可以去掉CONFIG_VMAP_STACK的配置 diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig select HAVE_ARCH_TRANSPARENT_HUGEPAGE - select HAVE_ARCH_VMAP_STACK select HAVE_ARM_SMCCC unpurged 0 50308 50308 unpurged 是kernel-4.14 上 remove vm area 的一个过渡状态 在kernel 4.9 remove_vm_area 时直接把VM_VM_AREA 清掉(va-flags ~VM_VM_AREA;) 但是Kernel-4.14 也会清掉VM_VM_AREA 但隨会标记成VM_LAZY_FREE 所以后面会被统计到unpurged 所以可以说是统计方法不同而已 (一个直接remove了 另一個被统计到unpurged 里) 所以在计算kernel-4.14的vmalloc usage page时需去掉该部分的size