安卓内存优化

背景

  安卓内存优化,涉及应用层、框架层、内核层。应用层侧重于使用层面,须有良好的内存使用习惯。框架层、内核层则是在aosp的基础,进一步优化系统内存管理机制。
  应用层内存优化,是为了app运行更加流畅,减少crash。框架层、内核层的内存优化,主要是为了提高可用内存、app保活数量、以及系统本身的流畅度。

内存基础知识

  1. 应用层

    避免内存泄漏、OOM、延迟使用对象等,详情略。
  2. 框架层

    1. 进程ADJ

      系统运行,内存过低时,根据进程优先级回收内存。ADJ代表进程优先级。
      Linux 内核 通过 proc文件系统,暴露 /proc/[pid]/oom_score_adj文件,来允许其他程序修改指定进程的优先级。值越小进程越重要。内存紧张时,系统会遍历所有进程,以确定杀死哪个进程,回收内存,此时会读取 oom_score_adj 这个文件的值。
      ProcessList.java中预定义了 oom_score_adj 的可能取值。
      进程ADJ详解
    2. 尽情期待

  3. 内核层

    1. 内存页分类

      1. 缓存页/文件页
        存储器有文件支持
        1. 私有页:干净页、脏页
        2. 共享页:干净页、脏页
      2. 匿名页
        没有文件支持,临时产生
    2. page fault

      缺页中断:访问虚拟内存内时,虚拟地址到物理地址未映射,或者有映射访问的page不在物理内存中,由cpu的MMU发出的中断。
      遇到缺页中断,内核会从硬盘加载文件到物理内存。
      缺页中断分类:
      1、Hard Page Fault 物理内存中没有对应的页帧
      2、Soft Page Fault 缺少VA到PA的映射。一般出现在多进程共享内存区域
      3、Invalid Page Fault· 无效缺页错误,比如访问的内存地址越界

    3. cpu访问设备简述

      cpu通过 地址总线 访问连接在地址总线上的所有外设,包括物理内存、IO设备等。但从cpu发出的访问地址,并非这些外设在地址总线上的物理地址,而是虚拟地址。由MMU将虚拟地址转换成物理地址,再从地址总线上发出。

    4. page table

      每个进程都有自己的页表,页表存储了进程中虚拟地址到物理地址的映射关系。MMU收到cpu的虚拟地址后查询页表。确定是否存在映射以及读写权限是否正常。

    5. memcg

      即memory cgroup。管理系统中一组进程的内存行为,对内存有不同需求的进程区分管理,实现更有效的资源利用和隔离。
      比如控制app的内存使用量。

    6. block io

      block I/O指的是块输入/输出,它是Linux内核中与块设备交互的输入/输出层

    7. 冻结进程

      app切换到后台,并且没有其他活动时,系统在一定时间内通过状态判断,将进程id迁移到冻结的cgroup节点上。主要为了提高性能、节约资源。

    8. 内存ZONE

      内存ZONE分为:ZONE_DMA、ZONE_DMA32、ZONE_NORMAL、ZONE_HIGHMEM、ZONE_MOVABLE
      内容在enum zone_type中

    9. allocstall

      内存性能指标,allocstall指的是分配内存时,由于内存不足,发生了内存回收的情况。 换句话说,叫内存分配停滞或者内存分配时延

    10. 内存分配流程(__alloc_pages函数)

mm/page_alloc.c

// 申请一块2^order的连续物理内存块
struct page *__alloc_pages(gfp_t gfp, unsigned int order, int preferred_nid, nodemask_t *nodemask){
	// 首次尝试从free快速分配
	page = get_page_from_freelist(alloc_gfp, order, alloc_flags, &ac);
	// 内存不足进入慢分配
	page = __alloc_pages_slowpath(alloc_gfp, order, &ac);
}
static inline struct page *__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, struct alloc_context *ac){
	// 尝试碎片整理后分配
	page = __alloc_pages_direct_compact(gfp_mask, order,alloc_flags, ac,INIT_COMPACT_PRIORITY,&compact_result);
	// 实在没办法了,尝试回收内存再分配
	page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac, &did_some_progress);
}
static inline struct page *__alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,unsigned int alloc_flags, const struct alloc_context *ac,unsigned long *did_some_progress){
	*did_some_progress = __perform_reclaim(gfp_mask, order, ac);
	page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
}
// 回收
static unsigned long __perform_reclaim(gfp_t gfp_mask, unsigned int order,const struct alloc_context *ac){
	progress = try_to_free_pages(ac->zonelist, order, gfp_mask, ac->nodemask);
}

mm/vmscan.c

unsigned long try_to_free_pages(struct zonelist *zonelist, int order,gfp_t gfp_mask, nodemask_t *nodemask){
	nr_reclaimed = do_try_to_free_pages(zonelist, &sc);
}
static unsigned long do_try_to_free_pages(struct zonelist *zonelist,struct scan_control *sc){
	// 记录allocstall次数
	if (!cgroup_reclaim(sc))
		__count_zid_vm_events(ALLOCSTALL, sc->reclaim_idx, 1);
}
  1. 尽情期待

内存优化

  1. 应用层

  2. 框架层

  3. 内核层

    内存管理机制优化
    1. 缺页中断
      Linux已有的机制。可以做到内存的惰性分配,使得内存用起来感觉比实际大小更大。
    2. 安卓swap机制
      1、使用zram进行压缩
      2、zram快满的时候,swap到flash中的文件
      swap到存储,有2种:
      1、swap 分区:在存储有独立分区
      2、swapfile:使用文件进行swap
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值