背景:為什么會(huì)去看這個(gè)?-有時(shí)候會(huì)遇到應(yīng)用啟動(dòng)的時(shí)候在systrace中看到大量的android.bg線程卫键,android.bg線程會(huì)搶占應(yīng)用啟動(dòng)過程的時(shí)候的cpu淑倾,從而拖慢了應(yīng)用啟動(dòng)的速度,因此才會(huì)來看看android.bg是什么東西.
總結(jié):
- android.bg是一個(gè)framework層提供的一個(gè)工具類休玩,方便在使用的時(shí)候來創(chuàng)建一個(gè)異步的線程狂鞋,擁有獨(dú)立的handler片择,在應(yīng)用啟動(dòng)過程中AMS也會(huì)使用這個(gè)工具類.
- 多次測(cè)試在應(yīng)用啟動(dòng)的過程中并不會(huì)必現(xiàn)大量的android.bg,且在pss收集的時(shí)間google在ProcessList中已經(jīng)配置好了骚揍,可對(duì)其做細(xì)微的調(diào)整字管,在這里看來暫時(shí)沒有必要調(diào)整.所以需要再進(jìn)一步進(jìn)行測(cè)試觀察拖慢應(yīng)用啟動(dòng)速度的其他原因.
next:該文的代碼只是一個(gè)引入,其中有更多的內(nèi)容暫未深糾.先貼收藏一些文檔后方便后續(xù)查看.
- Android applyOomAdjLocked http://www.reibang.com/p/ded0eb2e0182
- Android進(jìn)程調(diào)度之a(chǎn)dj算法 http://gityuan.com/2016/08/07/android-adj/
- Android進(jìn)程生命周期與ADJ http://gityuan.com/2015/10/01/process-lifecycle/
- Android LowMemoryKiller原理分析 http://gityuan.com/2016/09/17/android-lowmemorykiller/
- Android進(jìn)程調(diào)度之a(chǎn)dj算法 https://blog.csdn.net/ccjhdopc/article/details/52818012
1簡介
何為PSS, 概念可以從百度得知是實(shí)際物理內(nèi)存使用的大小信不,有個(gè)概念需要清楚嘲叔,這里所說的使用物理內(nèi)存的大小的計(jì)算方式也包括了使用共享庫的大小,但是不是全部大谢肴.
比如進(jìn)程A使用了libc庫借跪,進(jìn)程B也使用了libc庫,這個(gè)時(shí)候進(jìn)程A單獨(dú)占用物理內(nèi)存X, libc占用物理內(nèi)存Y
那么進(jìn)程A的PSS=X+Y/2酌壕,采用把共享so庫的內(nèi)存平分到使用它的進(jìn)程當(dāng)中,而進(jìn)程A的USS=X歇由,表示進(jìn)程A獨(dú)占的內(nèi)存不包括共享庫的內(nèi)存.
該文章主要討論AMS中是如何來收集PSS等信息卵牍,收集了又有什么用?
2 PSS收集
2.1 工具類
在android系統(tǒng)中提供了這樣工具類:
/**
* Shared singleton background thread for each process.
*/
public final class BackgroundThread extends HandlerThread {
private static BackgroundThread sInstance;
private static Handler sHandler;
private BackgroundThread() {
super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new BackgroundThread();
sInstance.start();
sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
public static BackgroundThread get() {
synchronized (BackgroundThread.class) {
ensureThreadLocked();
return sInstance;
}
}
public static Handler getHandler() {
synchronized (BackgroundThread.class) {
ensureThreadLocked();
return sHandler;
}
}
}
這個(gè)類主要是通過單例的方式提供了一個(gè)獨(dú)立的handler沦泌,該handler的looper對(duì)象不依賴使用這的主線程looper.
2.2 AMS中使用
AMS中有一種使用方式就是通過bg的形式來手機(jī)pss信息.
2.3 什么時(shí)候開始收集糊昙?
如下的函數(shù)是發(fā)送msg啟動(dòng)收集的地方
/**
* Schedule PSS collection of a process.
*/
void requestPssLocked(ProcessRecord proc, int procState) {
if (mPendingPssProcesses.contains(proc)) {
return;
}
if (mPendingPssProcesses.size() == 0) {
mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
}
if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of: " + proc);
proc.pssProcState = procState;
mPendingPssProcesses.add(proc);
}
調(diào)用它的地方只有一個(gè):
private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
long nowElapsed) {
......
......
......
if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
|| ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) {
if (false && mTestPssMode && app.setProcState >= 0 && app.lastStateTime <= (now-200)) {
// Experimental code to more aggressively collect pss while
// running test... the problem is that this tends to collect
// the data right when a process is transitioning between process
// states, which well tend to give noisy data.
long start = SystemClock.uptimeMillis();
long pss = Debug.getPss(app.pid, mTmpLong, null);
recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], mTmpLong[1], now);
mPendingPssProcesses.remove(app);
Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
+ " to " + app.curProcState + ": "
+ (SystemClock.uptimeMillis()-start) + "ms");
}
app.lastStateTime = now;
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
mTestPssMode, isSleepingLocked(), now);
if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
+ ProcessList.makeProcStateString(app.setProcState) + " to "
+ ProcessList.makeProcStateString(app.curProcState) + " next pss in "
+ (app.nextPssTime-now) + ": " + app);
} else {
if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
&& now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
mTestPssMode)))) {
requestPssLocked(app, app.setProcState);
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
mTestPssMode, isSleepingLocked(), now);
} else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
"Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
}
......
......
}
我們只關(guān)注applyOomAdjLocked中調(diào)用requestPssLocked的地方,其他地方暫時(shí)忽略谢谦;大家都知道applyOomAdjLocked是在updateOomAdjLocked中調(diào)用释牺,
而updateOomAdjLocked是在進(jìn)程的狀態(tài)發(fā)生變化的時(shí)候會(huì)進(jìn)行更新.
如下圖所示:
關(guān)于updateOomAdjLocked屬于內(nèi)存管理和進(jìn)程管理的內(nèi)容,這里就不詳細(xì)跟蹤回挽,會(huì)另起文章單獨(dú)在前人的基礎(chǔ)上在看看這一塊.
回到正題没咙,這里注意研究什么時(shí)候開始收集.
在一個(gè)新的進(jìn)程啟動(dòng)給的時(shí)候會(huì)在ActivityThread中的Main函數(shù)中會(huì)調(diào)用attach, 緊接著調(diào)用到AMS中的attachApplicationLocked中,最后調(diào)用了updateOomAdjLocked.
在applyOomAdjLocked中以上代碼中會(huì)判斷:
- 當(dāng)前進(jìn)程狀態(tài)的上一次進(jìn)程狀態(tài)時(shí)候?yàn)锳ctivityManager.PROCESS_STATE_NONEXISTENT
- 或者當(dāng)前狀態(tài)是否與上次不同.
如果滿足條件則會(huì)計(jì)算下一次收集pss時(shí)間:
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,//可以進(jìn)入進(jìn)一步看時(shí)間如何確定
mTestPssMode, isSleepingLocked(), now);
在接下來進(jìn)入updataoomadjlocked時(shí)候就會(huì)進(jìn)入else分支取requestPssLocked.
2.4 如何收集
final Handler mBgHandler = new Handler(BackgroundThread.getHandler().getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case COLLECT_PSS_BG_MSG: {
long start = SystemClock.uptimeMillis(); //開始收集的時(shí)間點(diǎn)
MemInfoReader memInfo = null;
synchronized (ActivityManagerService.this) {
if (mFullPssPending) {//是否進(jìn)行全面收集
mFullPssPending = false;
memInfo = new MemInfoReader();
}
}
if (memInfo != null) { //需要進(jìn)行全面收集的時(shí)候才會(huì)進(jìn)入這個(gè)分支
updateCpuStatsNow();//更新當(dāng)前cpu狀態(tài)
long nativeTotalPss = 0;
final List<ProcessCpuTracker.Stats> stats;//cpuTracker的List
synchronized (mProcessCpuTracker) {
stats = mProcessCpuTracker.getStats( (st)-> {
return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID;
});
}
final int N = stats.size();//stats大小
for (int j = 0; j < N; j++) {
synchronized (mPidsSelfLocked) {
if (mPidsSelfLocked.indexOfKey(stats.get(j).pid) >= 0) {
// This is one of our own processes; skip it.
continue;
}
}
/// M: DuraSpeed
//nativeTotalPss += Debug.getPss(stats.get(j).pid, null, null);
long nativePss = Debug.getPss(stats.get(j).pid, mTmpLong, null);
nativeTotalPss += nativePss;
synchronized (ActivityManagerService.this) {
ActivityStack stack = mStackSupervisor.getFocusedStack();
if (stack != null) {
ActivityRecord topActivityRecord = stack.topActivity();
if (topActivityRecord != null) {
mAmsExt.onRecordST(stats, j, (nativePss + mTmpLong[1]),
mPidsSelfLocked, topActivityRecord.packageName,
ActivityManagerService.this);
}
}
}
}
memInfo.readMemInfo();//讀取信息通過Debug讀取底層節(jié)點(diǎn)/proc/meminfo信息存儲(chǔ)在meminfo中
synchronized (ActivityManagerService.this) {
if (DEBUG_PSS) Slog.d(TAG_PSS, "Collected native and kernel memory in "
+ (SystemClock.uptimeMillis()-start) + "ms");
final long cachedKb = memInfo.getCachedSizeKb(); //獲取信息
final long freeKb = memInfo.getFreeSizeKb();
final long zramKb = memInfo.getZramTotalSizeKb();
final long kernelKb = memInfo.getKernelUsedSizeKb();
EventLogTags.writeAmMeminfo(cachedKb*1024, freeKb*1024, zramKb*1024,
kernelKb*1024, nativeTotalPss*1024);
mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
nativeTotalPss);//添加到進(jìn)程狀態(tài)中
}
}
int num = 0;
long[] tmp = new long[2];
do {
ProcessRecord proc;
int procState;
int pid;
long lastPssTime;
synchronized (ActivityManagerService.this) {
if (mPendingPssProcesses.size() <= 0) {//判斷待收集的數(shù)組中是否小于等于0千劈,決定是否退出
if (mTestPssMode || DEBUG_PSS) Slog.d(TAG_PSS,
"Collected PSS of " + num + " processes in "
+ (SystemClock.uptimeMillis() - start) + "ms");
mPendingPssProcesses.clear();
return;
}
proc = mPendingPssProcesses.remove(0);//移除頂部的process
procState = proc.pssProcState;//暫存進(jìn)程狀態(tài)
lastPssTime = proc.lastPssTime;//暫存進(jìn)程lastpssTime
if (proc.thread != null && procState == proc.setProcState
&& (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
< SystemClock.uptimeMillis()) { //如果進(jìn)程沒有掛祭刚,且當(dāng)前請(qǐng)求pss的進(jìn)程狀態(tài)等于上一次進(jìn)程狀態(tài),且在狀態(tài)改變后1s一秒內(nèi)
pid = proc.pid;
} else {
proc = null;
pid = 0;
}
}
if (proc != null) {//如果在進(jìn)程狀態(tài)切換后1s內(nèi),且進(jìn)程proc不為null
long pss = Debug.getPss(pid, tmp, null);// 獲得pss值(Debug類通過jni到cpp層讀取節(jié)點(diǎn)值并綜合計(jì)算結(jié)果返回)
synchronized (ActivityManagerService.this) {
if (pss != 0 && proc.thread != null && proc.setProcState == procState
&& proc.pid == pid && proc.lastPssTime == lastPssTime) {
num++;//已經(jīng)收集的進(jìn)程個(gè)數(shù)
recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1],
SystemClock.uptimeMillis());//記錄新的狀態(tài)
}
}
}
} while (true);
}
/// M: DuraSpeed
case AmsExt.COLLECT_PSS_FG_MSG: {
synchronized (ActivityManagerService.this) {
ActivityStack stack = mStackSupervisor.getFocusedStack();
if (stack != null) {
ActivityRecord topActivityRecord = stack.topActivity();
if (topActivityRecord != null) {
mAmsExt.onStoreRecord(null, -1, mPidsSelfLocked,
topActivityRecord.packageName, ActivityManagerService.this);
}
}
}
break;
}
}
}
};
如上涡驮,主要看COLLECT_PSS_BG_MSG消息是用來觸發(fā)pss收集的信息暗甥,COLLECT_PSS_FG_MSG消息應(yīng)該是MTK平臺(tái)快霸相關(guān)的內(nèi)容(略過).