logcat_events.txt
Line 26:
Line 3847: 01-02 13:03:58.149279 887 901 I am_pss : [16438,10036,com.android.systemui,52458496,47415296,146432]
16438
Pid 进程id
10036
Uid 用户id,Android作为单用户系统,Uid用于数据共享,可在AndroidManifest.xml中配置
com.android.systemui
进程名称
后面几个数字分别是
Pss
Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
Uss
Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
SwapPss
swap交换分区,表示交换分区内存占用?
am_pss 关键字
在源码中位置 \base\frameworks\base\services\core\java\com\android\server\am\EventLogTags.logtags
报告一个进程的内存使用情况
有规律的持续输出
# Report collection of memory used by a process
30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(PssKb|2|2),(UssKb|2|2)
调用
base\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
BackgroundThread recordPssSampleLocked
后台线程完成内存信息打印
/**
* Record new PSS sample for a process.
*/
void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long swapPss,
long now) {
EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
//打印Log
swapPss * 1024);
proc.lastPssTime = now;
proc.baseProcessTracker.addPss(pss, uss, true, proc.pkgList);
if (DEBUG_PSS) Slog.d(TAG_PSS,
"PSS of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
+ " state=" + ProcessList.makeProcStateString(procState));
if (proc.initialIdlePss == 0) {
proc.initialIdlePss = pss;
}
proc.lastPss = pss;
proc.lastSwapPss = swapPss;
if (procState >= ActivityManager.PROCESS_STATE_HOME) {
proc.lastCachedPss = pss;
proc.lastCachedSwapPss = swapPss;
}
final SparseArray
> watchUids
= mMemWatchProcesses.getMap().get(proc.processName);
Long check = null;
if (watchUids != null) {
Pair val = watchUids.get(proc.uid);
if (val == null) {
val = watchUids.get(0);
}
if (val != null) {
check = val.first;
}
}
if (check != null) {
if ((pss * 1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) {
boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
if (!isDebuggable) {
if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
isDebuggable = true;
}
}
if (isDebuggable) {
Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting");
final ProcessRecord myProc = proc;
final File heapdumpFile = DumpHeapProvider.getJavaFile();
mMemWatchDumpProcName = proc.processName;
mMemWatchDumpFile = heapdumpFile.toString();
mMemWatchDumpPid = proc.pid;
mMemWatchDumpUid = proc.uid;
BackgroundThread.getHandler().post(new Runnable() {
@Override
public void run() {
revokeUriPermission(ActivityThread.currentActivityThread()
.getApplicationThread(),
DumpHeapActivity.JAVA_URI,
Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
UserHandle.myUserId());
ParcelFileDescriptor fd = null;
try {
heapdumpFile.delete();
fd = ParcelFileDescriptor.open(heapdumpFile,
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
ParcelFileDescriptor.MODE_WRITE_ONLY |
ParcelFileDescriptor.MODE_APPEND);
IApplicationThread thread = myProc.thread;
if (thread != null) {
try {
if (DEBUG_PSS) Slog.d(TAG_PSS,
"Requesting dump heap from "
+ myProc + " to " + heapdumpFile);
thread.dumpHeap(true, heapdumpFile.toString(), fd);
} catch (RemoteException e) {
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fd != null) {
try {
fd.close();
} catch (IOException e) {
}
}
}
}
});
} else {
Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check
+ ", but debugging not enabled");
}
}
}
}
后台线程持续执行,并会有规律的输出 pss 信息
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();
MemInfoReader memInfo = null;
synchronized (ActivityManagerService.this) {
if (mFullPssPending) {
mFullPssPending = false;
memInfo = new MemInfoReader();
}
}
if (memInfo != null) {
updateCpuStatsNow();
long nativeTotalPss = 0;
final List stats;
synchronized (mProcessCpuTracker) {
stats = mProcessCpuTracker.getStats( (st)-> {
return st.vsize > 0 && st.uid < Process.FIRST_APPLICATION_UID;
});
}
final int N = stats.size();
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;
}
}
nativeTotalPss += Debug.getPss(stats.get(j).pid, null, null);
}
memInfo.readMemInfo();
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);
}
}
int num = 0;
long[] tmp = new long[2];
do {
ProcessRecord proc;
int procState;
int pid;
long lastPssTime;
synchronized (ActivityManagerService.this) {
if (mPendingPssProcesses.size() <= 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);
procState = proc.pssProcState;
lastPssTime = proc.lastPssTime;
if (proc.thread != null && procState == proc.setProcState
&& (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
< SystemClock.uptimeMillis()) {
pid = proc.pid;
} else {
proc = null;
pid = 0;
}
}
if (proc != null) {
long pss = Debug.getPss(pid, tmp, null);
synchronized (ActivityManagerService.this) {
if (pss != 0 && proc.thread != null && proc.setProcState == procState
&& proc.pid == pid && proc.lastPssTime == lastPssTime) {
//比对时间
num++;
recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1],
SystemClock.uptimeMillis());
}
}
}
} while (true);
}
}
}
};
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);
}
源码中EventLogTags并没有writeAmPss方法,ActivityManagerService.java目录也没有EventLogTags类,这个类通过EventLogTags.logtags生成
# Report collection of memory used by a process
30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(PssKb|2|2),(UssKb|2|2)
\out\target\common\obj\JAVA_LIBRARIES\services.core_intermediates\src\java\com\android\server\am\EventLogTags.java
/** 30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2) */
public static final int AM_PSS = 30047;
AM_PSS 对应 am_pss
值30047与 30047对应
AmPss 与 am_pss对应
public static void writeAmPss(int pid, int uid, String processName, long pss, long uss, long swappss) {
android.util.EventLog.writeEvent(AM_PSS, pid, uid, processName, pss, uss, swappss);
}
(Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2)
1|5 |3 2|2
前一个参数值类型
# The data type is a number from the following values:
# 1: int
# 2: long
# 3: string
# 4: list
# 5: float
#
后一个参数类型
# The data unit is a number taken from the following list:
# 1: Number of objects
# 2: Number of bytes
# 3: Number of milliseconds
# 4: Number of allocations
# 5: Id
# 6: Percent
# Default value for data of type int/long is 2 (bytes).