Android内存优化(四)系统级别的内存回收策略优化--process reclaim

曾经反编译过某厂商的framework代码,结合厂商机器的表现,发现了进程内存管理的部分逻辑,记录如下:
之前一直怀疑某厂商的AMS.updateOomAdjLocked()方法中,添加了进程管理逻辑,
结果是进程管理的代码还没核实,倒是找到了运行时proc reclaim逻辑,
在反编译的AMS.updateOomAdjLocked​()方法中,发现以下逻辑:

      try
      {
        if ((ActivityManagerDebugConfig.DEBUG_SWITCH) || (    ActivityManagerDebugConfig.DEBUG_OOM_ADJ)) {
          Slog.v(TAG_OOM_ADJ, "Trimming memory of " + localIndexOutOfBoundsException1.processName + " to " + i1);
        }
        SmartShrinker.reclaim(localIndexOutOfBoundsException1.pid, 4);
        localIndexOutOfBoundsException1.thread.scheduleTrimMemory(i1);
      }
      catch (RemoteException localRemoteException5)

我看了下SmartShrinker的实现,主体逻辑:

  public static final void reclaim(int paramInt1, int paramInt2)
  {
    if (ENABLE)
    {
      ProcessList.callProcReclaim(paramInt1, paramInt2);
      Log.w("RMS.SmartShrinker", "SmartShrinker is runing in pid =" + paramInt1 + " reclaim mode = " + paramInt2);
    }
  }

再看下callProcReclaim方法:

  public static final void callProcReclaim(int paramInt1, int paramInt2)
  {
    long l1 = SystemClock.elapsedRealtime();
    ByteBuffer localByteBuffer = ByteBuffer.allocate(16);
    localByteBuffer.putInt(54);
    localByteBuffer.putInt(paramInt1);
    localByteBuffer.putInt(paramInt2);
    writeLmkd(localByteBuffer);
    long l2 = SystemClock.elapsedRealtime();
    if (l2 - l1 > 250L) {
      Slog.w("ActivityManager", "SLOW call process reclaim: " + (l2 - l1));
    }
  }

由此可见这个策略是进程级别的proc reclaim,
运行时的proc reclaim由属性ro.config.hw_smart_shrink控制,
boolean bool = SystemProperties.getBoolean(“ro.config.hw_smart_shrink”, false)
在高端机上没有开,此属性没有设置,而在中低端机上设置为true
[ro.config.hw_smart_shrink]: [true]

运行时的proc reclaim时机?
全局搜了下,在AMS的两个接口中,updateOomAdjLocked和cleanUpRemovedTaskLocked
./com/android/server/am/ActivityManagerService.smali:12332: invoke-static {v13, v14}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/am/ActivityManagerService.smali:115272: invoke-static {v6, v7}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/am/ActivityManagerService.smali:115354: invoke-static {v2, v7}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/am/ActivityManagerService.smali:121014: invoke-static {v5, v7}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/pm/PackageManagerService$PackageHandler.smali:1605: invoke-static {v4, v10}, Lcom/android/server/SmartShrinker;->reclaim(II)V
./com/android/server/SystemServer.smali:1061: invoke-static {v2, v3}, Lcom/android/server/SmartShrinker;->reclaim(II)V
<1>ActivityManagerService.updateOomAdjLocked
在trim memory 操作时,对于重要性小于home的进程做process reclaim,基本都是不活跃的进程。
对应到代码位置:

if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
        && !app.killedByAm) {
    if (app.trimMemoryLevel < curLevel && app.thread != null) {
        try {
            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                    "Trimming memory of " + app.processName + " to " + curLevel);
            SmartShrinker.reclaim(app.pid, 4);
            app.thread.scheduleTrimMemory(curLevel);
        } catch (RemoteException e) {
  	 }

<2>ActivityManagerService​.cleanUpRemovedTaskLocked
看下smali文件,尝试还原了下逻辑,并将代码对应上,这个地方应该是有些进程不杀,只做trim memory 操作和proc reclaim操作

// Kill the running processes.
for (int i = 0; i < procsToKill.size(); i++) {
    ProcessRecord pr = procsToKill.get(i);
    if (pr != null && pr.curAdj >= 900 && pr.info.flags & 0x1) != 0 && pr.info.hwFlags & 0x2000000) == 0 ) {
        Slog.d(TAG, " the process " + pr.processName + " adj >= " + 900);
        try{
            SmartShrinker.reclaim(pr.pid, 4);
            pr.thread.scheduleTrimMemory(80);
        } catch (RemoteException localRemoteException) {}
        pr.trimMemoryLevel = 80;
    } else if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
            && pr.curReceiver == null) {
        pr.kill("remove task", true);
    } else {
        // We delay killing processes that are not in the background or running a receiver.
        pr.waitingToKill = "remove task";
    }
}

<3>ActivityManagerService.trimServicesAfterBoot​
原生代码上没有此代码,应该是厂商自己添加的接口,在ActivityManagerService.MainHandler的handleMessage​()使用
反编译逻辑比较多,暂不贴出
<4>SystemServer.run
根据smali文件还原逻辑,跟代码对上,

// Loop forever.
Slog.i(TAG, "Entered the Android system server main thread loop.");
SmartShrinker.reclaim(Process.myPid(),0x3)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");

<5>PackageManagerService$PackageHandler​.​doHandleMessage​
根据smali文件还原逻辑,跟代码对上,​在POST_INSTALL​处理逻辑中

// Add the args.info.getLocation for install exception statistics
    handlePackagePostInstall(childRes, grantPermissions, killApp,
            grantedPermissions, false, args.installerPackageName,
            args.observer, args.origin.getLocation());
}
SmartShrinker.reclaim(Process.myPid(),3)
// Log tracing if needed
if (args.traceMethod != null) {
    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod,
            args.traceCookie);
}

从上面的逻辑中看,往SmartShrinker传参时,传的3或者4,在SmarShrinker的定义为:
public static final int RECLAIM_ALL_MODE = 2;
public static final int RECLAIM_ANON_MODE = 1;
public static final int RECLAIM_INACTIVE_MODE = 4;
public static final int RECLAIM_SOFT_MODE = 3;

整体看,proc reclaim的时机有:
1:updateOomAdj 对于不活跃的重要性小于home的进程进程proc reclaim
2:cleanUpRemovedTaskLocked​ 清除task时,有些进程不杀掉,只做trim和proc reclaim(一键清理有很多App是杀不掉的,不知道和这个地方是否有关)
3:trimServicesAfterBoot​​ 开机启动的时候,对service proc reclaim(看smali中,还有对zygote的proc reclaim,通过ro.config.reclaim_zygote控制)
4:system server启动后,loop之前做一次proc reclaim
5:PMS的POST_INSTALL​ 消息处理逻辑,应该是安装完成后做proc reclaim

感觉这套已成体系,做的比较完善,开机的时候模块调用SmartShrinker进行进程的proc reclaim即可~
而且进程proc reclaim的内容分为all, anon,inactive,soft四种,分的更细一些,比如运行时,proc reclaim的是INACTIVE文件页,个人感觉比较合理

猜你喜欢

转载自blog.csdn.net/longlong2015/article/details/82975502
今日推荐