文档中心 > 芯片厂商开放

系统内存调优实战

更新时间:2017/08/17 访问次数:3649

文档内容拷贝自:codebase_host/yunhal/opendoc/zh/best_practice/memory.md
联系人:郑魁
版本: commit-id(ac0a9b01619b621cab753098d2c4650227d7fd90)

系统内存实战

1. 概述

本文档旨在帮助系统开发者了解系统当前内存状态, 分析内存占用分布. 并结合系统特点给出部分优化建议.

2. 系统内存分析

2.1 系统内存占用总览

通过以下常用的系统工具, 从多个维度了解当前系统内存状态.

/proc/meminfo

/proc/meminfo是了解Linux系统内存使用状况的主要接口,我们最常用的”free”、”vmstat”等命令就是通过它获取数据. 其中主要的项有:

  • MemFree: 空闲物理内存
  • Buffers: 块设备缓冲区,文件系统元数据
  • Cached: 文件缓存,包括映射和非映射的文件
  • AnonPages: 匿名页,用户进程mmap(不包括文件映射)产生,如heap。
  • Shmem统计的内容包括:shared memory + tmpfs。
  • SwapCached: 交换设备如zram的Cache
  • SwapTotal/SwapFree:swap空间大小,
  • KernelStack/PageTables:kernel 内存占用
  • SLAB:/proc/slabinfo
  • VmallocUsed:Alloc部分,/proc/vmallocinfo

参考: proc-meminfo

procrank

procrank 获取所有进程的内存使用的排行榜,排行是以Pss的大小而排序。procrank命令可以输出详细的VSS/RSS/PSS/USS内存指标,其中:

  • VSS – Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
  • RSS – Resident Set Size 实际使用物理内存(包含共享库占用的内存)
  • PSS – Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
  • USS – Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

参考:How to use procrank

Dumpsys meminfo

如果装有container, 可以使用Dumpsys meminfo tool来分析系统内存。

参考:Understanding How Your App Uses RAM

2.2 进程的内存占用分析

showmap

showmap 用来breakdown 应用的具体内存分布, 例如:

  • .so 占用
    library_memory

  • Gpu mapped (e.g 高通平台的kgsl)
    gpu_memory

  • vm
    v8_memory

  • anon/heap
    anon_memory

进程GPU内存占用

通常UI进程会使用较多GPU内存,其中包括gl context的开销和egl er的开销, 以高通平台为例:

命令: cat /sys/kernel/debug/kgsl/proc/ /mem
这里gl context的开销主要是texture:
kgsl-gl

egl buffer内存通常基于ION:
kgsl-egl

*注意:不同硬件平台的gpu debugfs不同,并且输出也不一样。
比如mali平台需要查看:
cat /sys/kernel/debug/mali0/gpu_memory

2.3 深入到进程的关键模块

通过2.2的分析可以知道进程内存占用的分布,对于关键的模块需要深入分析。

JS Engine内存占用
Javascript是YunOS基本开发语言,桌面以及很多服务都是基于JS。vm的内存通常在进程的内存占用中较多。

用法:./vmcmd –memory <进程号>
输出:adb logcat | grep v8
vm-memory

  • New space (绝大部分的js短生命周期的对象),
  • Old space (成员变量为引用的对象)
  • Code space(生成的汇编代码对象)
  • Map space(隐藏类对象,vm内部使用的一些对象)
  • Large obj space(大于600KB的大对象),
  • used表示每个space当前存活对象的总大小KB,
  • available表示还可分配给js对象的内存总大小KB,
  • committed表示该space向系统申请了的虚内存大小KB,
  • physical表示使用的物理内存大小KB。
  • All space表示几个spaces的累计值,
  • External memory reported表示外部注册进来的allocator分配的对象总大小KB
  • scavenger-gc表示启动以来发生的young-gc次数,
  • full-gc表示启动以来发生的full-gc次数。

AgilEngine 内存占用

AgilEngine是YunOS的UI渲染引擎,一般agil的主要内存占用是应用的bitmap/texture开销。可以通过agilcmd工具快速定位:

用法:./agilcmd –mem_info <进程号>

输出举例:

agil-memory

H5/Webengine 内存占用

H5应用也是YunOS的重要生态,系统集成了对WebEngine内存占用的分析工具:

用法:agilcmd –webtrace_begin <进程号>
… play h5 page …
agilcmd –webtrace_end <进程号>

输出:
webengine-memory

参考:Memory-infra Doc

3. 优化建议

3.1 避免过多系统常驻服务

不必要的常驻服务对内存和其他资源都是浪费,要避免过多的常驻服务,尤其是JS服务。目前主要的处理手段有:

  • Service/provider的按需启动:对于业务相关的服务最好可以在应用启动的时候再按需启动后台服务。
  • 对于支持common业务的服务,为了满足应用启动性能可以将服务和系统systemservice合并。
  • Service/provider 的主动退出。在服务长时间空闲的状态下可以主动退出以释放内存,provider在自身逻辑中,需要在没有应用使用的情况下退出对接步骤如下:
    1. 应用provider继承DataProvider, 并实现如下接口:
      onIdleTimeout() {
      }
    2. 如果应用provider需要退出,在onIdleTimeout接口实现中,添加自己的资源清理和退出的逻辑,并调用stopPage()接口,通知DPMS退出page;
    3. 当provider的最后一个client释放掉连接后,provider框架会启动一个60s的timer,当60s timeout之后,provider框架会调用provider对象的onIdleTimeout接口,完成退出。

3.2 Page合并

如何合并多个page, 请参考DPMS相关文档.通过合并多个js进程可以减少VM的内存开销。、

3.3 UI Page的后台处理

UI进程切换到后台之后,可以释放部分内存资源,比如:

  • 系统会释放surface相关的资源,比如ION buf.
  • 应用可以主动触发GC:*void v8::Isolate::LowMemoryNotification() (参考vm/v8/include/v8.h)*
  • 应用可以释放image资源: image(src = Null), agil会在30s之后删除相关texture
  • 应用可以把UI进程退出,仅保留service.比如后台音乐的场景。

3.4 编写内存友好的UI

请参考CAF相关文档, 这里仅强调对于image资源的使用。虽然Decoded pixmap会很快被agil释放, 但是仍需要谨慎处理image带来的内存开销。

  • 避免无用的高分辨率image
  • 是否需要atlas
  • 对于隐藏的image节点 set image source = null来释放gpu texture

FAQ

关于此文档暂时还没有FAQ
返回
顶部