内存问题快速定位

内存问题快速定位

一、重要性

内存问题是制约性能的很大的一个问题,往往具有隐蔽性和毁灭性,但是对于一般性问题还是有通用的方法可以快速进行定位;

二、常见问题

  1. 内存标准问题:
    1. 现在统一按照内存3.0标准施行:小米应用内存标准3.0(试行版)
    2. 对于场景内存、老化内存,需要注意分辨率,如果为2K分辨率,需要在验收值的基础上前台1.2,后台1.1;
  2. 测试问题:
    1. 桌面未退到后台问题,通过数据中的截图可以进行判断桌面在后台时是否已经跳转到其他应用;
    2. 最近任务没有清除的问题;
    3. 场景测试中,case测完之后没有杀死进程,通过PID进行判断;
    4. 数据不全(hprof、meminfo、smaps等数据未提供),不能进行分析的问题,需要测试进一步提供;

三、通过meminfo快速定位问题思路

  1. meminfo中主要查看如下内容,其他的根据情况再进行分析;
    1. Java堆:Java Heap + (Dalvik Heap对应的SwapPss Dirty)
    2. Native堆:Native Heap + (Native Heap对应的SwapPss Dirty)
    3. Code占用:主要看.apk、.jar、.so,当然还包括.ttf、.dex、.art、.oat;
    4. Graphics占用
      1. EGL mtrack:与可见的window有关,主要为buffer所占用的空间,可查看可见的window个数是否存在异常;
      2. GL mtrack:主要与渲染相关,业务端无法进一步拆解;
    5. Views:view的个数;
    6. ViewRootImpl:窗口的个数;
    7. Activities:activity的个数,桌面可以关注下;
  2. 了解了以上的基本信息后,在面对内存问题时,需要通过查看meminfo针对前台、后台、峰值等关键点的对比,来确定影响内存的最主要因素,然后进行快速定位,以下提供了各个部分的快速定位方法:
    1. Java堆内存占用高的话,需要通过AS的Profiler打开hprof文件进行分析:
      1. 查看是否存在leaks,如果有,通过点击leaks,查看GCRoot,转给相关业务;
      2. 没有leaks的通用思路:
        1. 通过Shallow Size按照从大到小的顺序进行排序,从占用高的内存开始进行逐一排查,排查的思路:看是否存在很多相同的实例,通过GCRoot进行引用链的查看,转给相关的业务;
      3. 几个需要特殊查看的类:
        1. MiuiExpandableNotificationRow:通知的数数,通知的个数越多,内存会越大;需要根据测试内容判断通知个数的必要性;
        2. ShortCutInfo:桌面图标的数量,处理思路与通知一致;
        3. QSFragment,QSPager 数量,超过1则可认为存在泄漏,转给控制中心即可;
      4. 线程数目排查,主要搜索Thread[],查看所有线程的总数目如果大于150则怀疑存在问题,需要通过mThreadName查看是否存在多个相同名字的线程被创建,然后再进一步查看线程被创建的位置,从而定位问题,转给相应的owner;
    2. Native堆占用高,从两个纬度进行分析:
      1. 结合hprof文件,查看bitmap的占用情况;
      2. 通过NativeHeapInsight进行定位;
    3. Code占用内存高,需要通过脚本拆解smaps,可以清楚看到具体哪些内容占用多少内存;
    4. Graphics占用内存高,分两种:
      1. EGL高:
        1. 首先判断是前台还是后台,后台的情况下window不可见,EGL的内存应该进行回收,如果出现后台EGL内存占用较高,没有进行及时回收的问题,需要找内存优化组进行定位问题;
        2. 如果在前台,查看当前显示的窗口为哪个,一个窗口占用EGL的基本算法:
        3. ​ 内存占用 (Mb)=宽度×高度×每像素占用4字节数/1204x4;
        4. ​ 例如:3200x1440分辨率的屏幕,一个全尺寸的window在显示时,EGL的占用:
        5. ​ 3200x1440x4/1024x4=72M;
        6. 以此为基准进行大致的分析,当然除了窗口播放视频也会导致EGL增高,一般场景不涉及;
      2. GL高,直接转内存优化组帮忙定位;
    5. view个数多:如果数量过大,比如超过3000,要结合hprof文件,搜索view,过滤后对个数进行排序,从上往下查看;
    6. ViewRootImpl个数多
      1. 桌面全面屏手势的窗口有三个,桌面占用一个窗口;如果出现多或者少,首先查看Launcher是否发生了泄露;
      2. 系统UI:一般是11个或者12个,如果超出了5个以上,通过dumpmeminfo 后还不能下降,需要找Framework的窗口模块的同学进行分析确认是否存在泄露;
    7. Activities:个数异常:
      1. 桌面就1个,多出则存在泄露,通过Hprof直接定位;
      2. 系统UI 0 个,存在问题也可以通过Hprof进行定位;

四、写在最后

以上内容包括了基本的内存问题,但是不能盖全,内存问题复杂多变,需要长时间的经验积累,希望以上内容可以抛砖引玉,给大家以启发;

具体操作可参考文档:系统UI内存优化小结