android.bg,[Android]AMS-PSS
背景:为什么会去看这个?-有时候会遇到应用启动的时候在systrace中看到大量的android.bg线程,android.bg线程会抢占应用启动过程的时候的cpu,从而拖慢了应用启动的速度,因此才会来看看android.bg是什么东西.
总结:
android.bg是一个framework层提供的一个工具类,方便在使用的时候来创建一个异步的线程,拥有独立的handler,在应用启动过程中AMS也会使用这个工具类.
多次测试在应用启动的过程中并不会必现大量的android.bg,且在pss收集的时间google在ProcessList中已经配置好了,可对其做细微的调整,在这里看来暂时没有必要调整.所以需要再进一步进行测试观察拖慢应用启动速度的其他原因.
next:该文的代码只是一个引入,其中有更多的内容暂未深纠.先贴收藏一些文档后方便后续查看.
1简介
何为PSS, 概念可以从百度得知是实际物理内存使用的大小,有个概念需要清楚,这里所说的使用物理内存的大小的计算方式也包括了使用共享库的大小,但是不是全部大小.
比如进程A使用了libc库,进程B也使用了libc库,这个时候进程A单独占用物理内存X, libc占用物理内存Y
那么进程A的PSS=X+Y/2,采用把共享so库的内存平分到使用它的进程当中,而进程A的USS=X,表示进程A独占的内存不包括共享库的内存.
该文章主要讨论AMS中是如何来收集PSS等信息,收集了又有什么用?
2 PSS收集
2.1 工具类
在android系统中提供了这样工具类:
/**
* 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;
}
}
}
这个类主要是通过单例的方式提供了一个独立的handler,该handler的looper对象不依赖使用这的主线程looper.
2.2 AMS中使用
AMS中有一种使用方式就是通过bg的形式来手机pss信息.
2.3 什么时候开始收集?
如下的函数是发送msg启动收集的地方
/**
* 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);
}
调用它的地方只有一个:
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));
}
......
......
}
我们只关注applyOomAdjLocked中调用requestPssLocked的地方,其他地方暂时忽略;大家都知道applyOomAdjLocked是在updateOomAdjLocked中调用,
而updateOomAdjLocked是在进程的状态发生变化的时候会进行更新.
如下图所示:
updateOomAdjLocked更新地方
关于updateOomAdjLocked属于内存管理和进程管理的内容,这里就不详细跟踪,会另起文章单独在前人的基础上在看看这一块.
回到正题,这里注意研究什么时候开始收集.
在一个新的进程启动给的时候会在ActivityThread中的Main函数中会调用attach, 紧接着调用到AMS中的attachApplicationLocked中,最后调用了updateOomAdjLocked.
在applyOomAdjLocked中以上代码中会判断:
当前进程状态的上一次进程状态时候为ActivityManager.PROCESS_STATE_NONEXISTENT
或者当前状态是否与上次不同.
如果满足条件则会计算下一次收集pss时间:
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,//可以进入进一步看时间如何确定
mTestPssMode, isSleepingLocked(), now);
在接下来进入updataoomadjlocked时候就会进入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(); //开始收集的时间点
MemInfoReader memInfo = null;
synchronized (ActivityManagerService.this) {
if (mFullPssPending) {//是否进行全面收集
mFullPssPending = false;
memInfo = new MemInfoReader();
}
}
if (memInfo != null) { //需要进行全面收集的时候才会进入这个分支
updateCpuStatsNow();//更新当前cpu状态
long nativeTotalPss = 0;
final List 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读取底层节点/proc/meminfo信息存储在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);//添加到进程状态中
}
}
int num = 0;
long[] tmp = new long[2];
do {
ProcessRecord proc;
int procState;
int pid;
long lastPssTime;
synchronized (ActivityManagerService.this) {
if (mPendingPssProcesses.size() <= 0) {//判断待收集的数组中是否小于等于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;//暂存进程状态
lastPssTime = proc.lastPssTime;//暂存进程lastpssTime
if (proc.thread != null && procState == proc.setProcState
&& (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
< SystemClock.uptimeMillis()) { //如果进程没有挂,且当前请求pss的进程状态等于上一次进程状态,且在状态改变后1s一秒内
pid = proc.pid;
} else {
proc = null;
pid = 0;
}
}
if (proc != null) {//如果在进程状态切换后1s内,且进程proc不为null
long pss = Debug.getPss(pid, tmp, null);// 获得pss值(Debug类通过jni到cpp层读取节点值并综合计算结果返回)
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);
}
/// 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消息是用来触发pss收集的信息,COLLECT_PSS_FG_MSG消息应该是MTK平台快霸相关的内容(略过).
android.bg,[Android]AMS-PSS相关推荐
- 【Android源码-AMS】(一)Instrumentation类解析
注:转载请注明来自Nemo,http://blog.csdn.net/nemo__ 一.包名 android.app.Instrumentation 这里研究AMS中的Instrum ...
- Android ActivityManagerService(AMS)的Activity管理
对于AMS来讲,Activity管理是它的核心工作,前面两篇文章都是讲AMS的启动流程和进程的管理,这两篇文章其实是为本文做铺垫的,只有理解了前面两篇文章才能更好地理解AMS的activity管理.在 ...
- Android 7.1.2(Android N) Android系统启动流程
Android 7.1.2(Android N) Android系统启动流程 源码: system/core/rootdir/ init.rc init.zygote64.rc system/core ...
- Android O Android P 自定义开机广播
背景 一般来说,我们都是用的监听android.intent.action.BOOT_COMPLETED. 但凡稍有些经验的开发者都知道,这个广播很慢,非常慢.因为它是一个有序广播,根据优先级来的,而 ...
- android之android.intent.category.DEFAULT的用途和使用
1.要弄清楚这个问题,首先需要弄明白什么是implicit(隐藏) intent什么是explicit(明确) intent. Explicit Intent明确的指定了要启动的Acitivity , ...
- android:layout_with=,android – 难以理解layout_alignWithParentIfMissing
这仅适用于使用RelativeLayout时. 如果您将元素设置为一个其他元素,则表示该元素位于该元素的左侧. 但是如果这个元素会丢失,因为你删除它,例如它将与父对齐. 举个例子 android:la ...
- [Android Studio] Android Studio常用快捷键
[Android Studio] Android Studio常用快捷键 (会持续更新)这边讲的常用快捷键是指做完Keymap到Eclipse后的,不是纯Android Studio的,这边主要讲下比 ...
- Android利用android:indeterminateDrawable来实现ProgressBar三种方式
方式1:(效果为补间动画一样) [html] view plaincopyprint? <ProgressBar android:layout_width="wrap_content& ...
- Android之Android实现浮层的上下滑动(支持内部添加View)
前言 我K,今天居然是情人节,对于资深的单身狗来说,简直是个噩耗,今天注定是各种秀恩爱,心塞中.... 话题到此结束,管他什么情人节,今天给大家带来的是一个浮层的上下滑动,浮层滑动时分三种状态:全部显 ...
最新文章
- sublime设置tab为四个空格
- 写出程序删除链表中的所有接点
- 自动驾驶汽车想成为主流?先过了这十二关再说
- 九江学院计算机主任黄冬久,陈春生副校长到实验中间调研引导工作
- python私有方法应用场景_Python私有属性私有方法应用实例解析
- postgreSQL源码分析——索引的建立与使用——总结篇
- 物联网技术周报第 109 期: 从设计理念解读实时操作系统 RT-Thread
- 修改centos6.5的时区
- enable pen pressure in ps
- NeatUpload 的使用
- Tableau数据连接与加载(数据提取)
- 软件工程 | 第三章 需求分析
- 什么是无线射频识别技术(RFID)
- JavaScript 学习中
- 树莓派3B+ wifi 5G连接
- 四川大学计算机专业调剂,四川大学计算机学院(软件学院)2019考研调剂信息...
- 密码学数学基础——群、环、域
- QT5百度地图开发学习——地图显示
- msata、mini pcie 、pcie x4接口引脚定义及原理图方案设计
- Spring Cloud Alibaba Nacos 分布式配置
热门文章
- macbook数据线连接手机_MacBook可以为iPhone进行快充吗?用MacBook为iPhone充电好不好?...
- html5新增表单控件和表单属性
- java线程的小问题与回答
- SQL SERVER 2008 R2最大并发连接数修改为2后,SQL连接无法超过2个。
- OCX控件注册相关(检查是否注册,注册,反注册)
- c语言分治算法之归并排序,分治算法之归并排序
- python数据库实现注册函数_10.注册和登录功能实现(3)—— 注册数据写入数据库...
- 从零开始学前端:CSS复合选择器 --- 今天你学习了吗?(CSS:Day10)
- 观、砺、破——我的算法之道
- Python批量整理文件名小案例(附公众号第一批赠书活动中奖名单)