当前用户越来越关心APP的启动速度.而APP的启动和很多因素相关.
其中eMMC的读写性能一般和HW有关,可做的工作不多.对于CPU的频率,大多数的芯片vendor 也在App启动是采用了boost,也就是需要把CPU 运行在maxfreq.而App framework 的优化是andorid的code,这当中有很多工作可做.App 代码的优化,需要APP 开发者进行相关代码的优化.
本文将提供碰到的需要在App framework中的代码优化patch.
问题描述,
在chrome的启动中,发现chrome启动比较慢.其system server 的systracelog 如下.
从systrace log中,我们可以看到AMS 进行了3次kill empty process ,而每次kill 一个process大概需要100ms,总共就需要300ms的操作,其是一个非常费时的操作.如果在启动过程中,频繁出现killempy process 势必影响app的启动时间.
显易而见,其一种方法是提高emptyprocess number.这种方法有一个缺点是这个number需要提高多多少合适.如果太大有可能会由于memory吃紧从而triggerLMK.有可能是APP启动速度更慢.目前其default参数是16.我们可以把ro.sys.fw.bg_apps_limit的值改为比较高的值如50,这需要调试.
static final int MAX_CACHED_APPS= SystemProperties.getInt("ro.sys.fw.bg_apps_limit",32);
static final booleanUSE_TRIM_SETTINGS = static final intEMPTY_APP_PERCENT =SystemProperties.getInt("ro.sys.fw.empty_app_percent",50);
emptyProcessLimit =ProcessList.computeEmptyProcessLimit(mProcessLimit);
public static intcomputeEmptyProcessLimit(int totalProcessLimit) {
if(USE_TRIM_SETTINGS &&allowTrim()) {
return totalProcessLimit*EMPTY_APP_PERCENT/100;
} else {
return totalProcessLimit/2;
}
}
另一种方法便是在App启动的过程中,我们不需要kill任何进程及时是cache的process和empty的process达到了上限.其patch 如下.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.javab/services/core/java/com/android/server/am/ActivityManagerService.java
old mode 100644
new mode 100755
index d2f573b..535300d
---a/services/core/java/com/android/server/am/ActivityManagerService.java
+++b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19071,6 +19072,7 @@ public final classActivityManagerService extends ActivityManagerNative
}
final voidupdateOomAdjLocked() {
+
finalActivityRecord TOP_ACT = resumedAppLocked();
finalProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
final longnow = SystemClock.uptimeMillis();
@@ -19232,6 +19234,8 @@ public final classActivityManagerService extends ActivityManagerNative
}
applyOomAdjLocked(app, true, now);
+ boolean isStartingApp=false;
+ isStartingApp=mStackSupervisor.mLaunchingActivity.isHeld();
//Count the number of process types.
switch (app.curProcState) {
@@ -19240,19 +19244,34 @@ public final classActivityManagerService extends ActivityManagerNative
mNumCachedHiddenProcs++;
numCached++;
if (numCached > cachedProcessLimit) {
+ if(!isStartingApp)
app.kill("cached #" + numCached, true);
}
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
if (numEmpty > ProcessList.TRIM_EMPTY_APPS
&&app.lastActivityTime < oldTime) {
+ if(!isStartingApp)
app.kill("empty for "
+((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
/ 1000) + "s",true);
}
} else {
numEmpty++;
if (numEmpty > emptyProcessLimit) {
+ if(!isStartingApp)
app.kill("empty #" + numEmpty, true);
}
}
break;
@@ -19268,7 +19287,10 @@ public final classActivityManagerService extends ActivityManagerNative
// definition not re-use the same process again, and it is
// good to avoid having whatever code was running in them
// left sitting around after no longer needed.
+ if(!isStartingApp)
app.kill("isolated not needed", true);
}else {
// Keeping this process, update its uid.
final UidRecord uidRec = app.uidRecord;