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文件頁,個人感覺比較合理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章