当前位置: 首页 > news >正文

网站打开太慢什么原因android最新版本

网站打开太慢什么原因,android最新版本,网站域名怎么设置,建设一个网站要多基于版本#xff1a;Android S 0. 前言 在之前的两篇博文《Android 中app内存回收优化(一)》和 《Android 中app内存回收优化(二)》中详细剖析了 Android 中 app 内存优化的流程。这个机制的管理通过 CachedAppOptimizer 类管理#xff0c;为什么叫这个名字#xff0c;而不…基于版本Android S 0. 前言 在之前的两篇博文《Android 中app内存回收优化(一)》和 《Android 中app内存回收优化(二)》中详细剖析了 Android 中 app 内存优化的流程。这个机制的管理通过 CachedAppOptimizer 类管理为什么叫这个名字而不叫 AppCompact 等在之前的两篇博文中也提到了因为该类中还管理了一个重要功能freezer一个针对应用进程长期处于 Cached 状态的优化。 在之前博文《app freezer 原理 R 版本》中简单的剖析了app freeze / unfreeze 的流程但从代码逻辑上来看笔者觉得 R 版本上有些逻辑是存在问题的好在S 版本中都修复了。 本文将以 R 版本的原理为基础对 S 版本进行对比分析。 1. freezer 触发 同 R 版本中S 版本的触发也是在 applyOomAdjLSP() 函数中调用 updateAppFreezeStateLSP() 来确认是否冻结进程 frameworks/base/services/core/java/com/android/server/am/OomAdjuster.javaprivate void updateAppFreezeStateLSP(ProcessRecord app) {// 确认该功能是否使能如果没有使能则返回if (!mCachedAppOptimizer.useFreezer()) {return;}// S 版本新加的确认应用是否可以豁免if (app.mOptRecord.isFreezeExempt()) {return;}// S 版本中cached进程优化相关的属性都放到了mOptRecord中管理final ProcessCachedOptimizerRecord opt app.mOptRecord;// 如果进程处于frozen状态但shouldNotFreeze变成true需要解冻if (opt.isFrozen() opt.shouldNotFreeze()) {mCachedAppOptimizer.unfreezeAppLSP(app);return;}// 确定adj是进入freeze 还是 unfreeze 流程final ProcessStateRecord state app.mState;if (state.getCurAdj() ProcessList.CACHED_APP_MIN_ADJ !opt.isFrozen() !opt.shouldNotFreeze()) {mCachedAppOptimizer.freezeAppAsyncLSP(app);} else if (state.getSetAdj() ProcessList.CACHED_APP_MIN_ADJ) {mCachedAppOptimizer.unfreezeAppLSP(app);}} 该函数与 R 版本基本逻辑差不多稍微有些差异 进程有了是否freeze 豁免的功能当应用设置了 INSTALL_PACKAGES 的权限之后该应用处于豁免状态详细看 ProcessList.startProcessLocked() 函数S 版本中cached进程的一些状态统一由ProcessRecord 中的 mOptRecord 维护最后再unfreeze 调用时不再判断app 是否处于 frozen因为这部分逻辑判断会在 unfreeze 函数中判定这让代码更简介R 版本中有些多余 2. CachedAppOptimizer.init() 对于CachedAppOptimizer 的构造调用以及 init() 函数的触发流程可以参考《Android 中app内存回收优化(二)》 一文第 1 节 和 第 2 节。 frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.javapublic void init() {...DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,ActivityThread.currentApplication().getMainExecutor(),mOnNativeBootFlagsChangedListener);mAm.mContext.getContentResolver().registerContentObserver(CACHED_APP_FREEZER_ENABLED_URI, false, mSettingsObserver);synchronized (mPhenotypeFlagLock) {...updateUseFreezer();...}} 相比较与 R 版本这里多了两个功能 新加一个 freeze_debounce_timeout 属性发生变化的 listener当该属性变化时会调用 updateFreezerDebounceTimeout() 进行更新新加了 cached_apps_freezer 属性值发生变化的 observer 在 R 版本中freeze timeout 是10min使用的是常量。而在 S 版本中将该值设计为可变的用户可以通过 DeviceConfig 进行修改。当发生变化时会调用 updateFreezerDebounceTimeout()进行更新。 另外在 S 版本中对 cached_apps_freezer 的值做了一个observer及时控制 freezer 的使能。 2.1 updateUseFreezer() private void updateUseFreezer() {// 获取 settings中属性 cached_apps_freezer的值同R 版本final String configOverride Settings.Global.getString(mAm.mContext.getContentResolver(),Settings.Global.CACHED_APPS_FREEZER_ENABLED);if (disabled.equals(configOverride)) {mUseFreezer false;} else if (enabled.equals(configOverride)|| DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,KEY_USE_FREEZER, DEFAULT_USE_FREEZER)) {mUseFreezer isFreezerSupported();updateFreezerDebounceTimeout();} else {mUseFreezer false;}final boolean useFreezer mUseFreezer;// enableFreezer() would need the global ActivityManagerService lock, post it.mAm.mHandler.post(() - {if (useFreezer) {Slog.d(TAG_AM, Freezer enabled);enableFreezer(true);if (!mCachedAppOptimizerThread.isAlive()) {mCachedAppOptimizerThread.start();}if (mFreezeHandler null) {mFreezeHandler new FreezeHandler();}Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),mCompactionPriority);} else {Slog.d(TAG_AM, Freezer disabled);enableFreezer(false);}});} 针对 R 版本也做了个优化将 enableFreezer() 的处理进行异步处理因为在 S 版本中做了一个很大的调整。详细查看下文第 4 节。 freezer 功能是否使能用流程图说明比较清晰 需要注意的是在获取freezer 节点的时候与R 版本有所不同 R 版本是直接指定节点 /sys/fs/cgroup/freezer/cgroup.freezeS 版本是通过函数 getFreezerCheckPath() 向libprocessgroup 中查找 pid 所对应的节点 3. cgroups 简介 这里不再补充详细可以查看 R 版本或《Android 中 cgroup抽象层详解》 这里需要注意的是R 版本中的 freezer 中通过 /sys/fs/cgroup/freezer/cgroup.freeze 来确定是否使能 freezer通过 /sys/fs/cgroup/freezer/cgroup.procs 来进行 frozen / unfrozen 操作。 而在 S 版本中frozen/unfrozen 的操作通过 /sys/fs/cgroup/uid_xxx/pid_xxx/cgroup.freeze 节点。 在 S 版本中 cgroups.json 有所不同 Cgroups2: {Path: /sys/fs/cgroup,Mode: 0755,UID: system,GID: system,Controllers: [{Controller: freezer,Path: .,Mode: 0755,UID: system,GID: system}]} 不再出现 freezer 目录而是直接在 /sys/fs/cgroup 目录下创建 uid_xxx/pid_xxx 目录。 详细看下面第 5.2.1 节。 4. enableFreezer() frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.javapublic synchronized boolean enableFreezer(boolean enable) {if (!mUseFreezer) {return false;}if (enable) {mFreezerDisableCount--;if (mFreezerDisableCount 0) {return true;} else if (mFreezerDisableCount 0) {Slog.e(TAG_AM, unbalanced call to enableFreezer, ignoring);mFreezerDisableCount 0;return false;}} else {mFreezerDisableCount;if (mFreezerDisableCount 1) {return true;}}// Override is applied immediately, restore is delayedsynchronized (mAm) {synchronized (mProcLock) {mFreezerOverride !enable;Slog.d(TAG_AM, freezer override set to mFreezerOverride);mAm.mProcessList.forEachLruProcessesLOSP(true, process - {if (process null) {return;}final ProcessCachedOptimizerRecord opt process.mOptRecord;if (enable opt.hasFreezerOverride()) {freezeAppAsyncLSP(process);opt.setFreezerOverride(false);}if (!enable opt.isFrozen()) {unfreezeAppLSP(process);// Set freezerOverride *after* calling unfreezeAppLSP (it resets the flag)opt.setFreezerOverride(true);}});}}return true;} 代码与 R 版本 不同这里通过 mAm.mProcessList.forEachLruProcessesLOSP() 对每个LRU 中的进程进行确认。 进程中引入了 mOptRecord.mFreezerOverride 属性用以标记对某个进程是否进行 disable freezer 操作。若该值为 true则表示进程被 disable freezer 过。此时如果再次 enable需对进程进行 freeze 请求。 当然CachedAppOptimizer 类中也有这样的成员变量 mFreezerOverride这个用以控制从外部调用的 freezeAppAsyncLSP()。如果该值为 true则表示disable freezer了外部如果有调用 freezeAppAsyncLSP()则不需要去处理。 5. freezeAppAsyncLSP() void freezeAppAsyncLSP(ProcessRecord app) {final ProcessCachedOptimizerRecord opt app.mOptRecord;if (opt.isPendingFreeze()) {// Skip redundant DO_FREEZE messagereturn;}mFreezeHandler.sendMessageDelayed(mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),mFreezerDebounceTimeout);opt.setPendingFreeze(true);} 相比较 R 版本这里做了一个保护防止反复进行 freeze 请求。 另外timeout 从 R 版本中的常量 FREEZE_TIMEOUT_MS 改成可变的 debounce timeout。 注意冻结时异步操作使用 CachedAppOptimizer类中定义的 ServiceThread 进行而解冻是东部操作没有通过 ServiceThread。 5.1 freeze 消息处理 public void handleMessage(Message msg) {switch (msg.what) {case SET_FROZEN_PROCESS_MSG:synchronized (mAm) {freezeProcess((ProcessRecord) msg.obj);}break;case REPORT_UNFREEZE_MSG:int pid msg.arg1;int frozenDuration msg.arg2;String processName (String) msg.obj;reportUnfreeze(pid, frozenDuration, processName);break;default:return;}} 对于 freezer 一共有两个消息REPORT_UNFREEZE_MSG 这个消息是在 unfreeze 之后进行记录的。 本文重点来看下 freeze 的消息处理这里看到最终调用的是 freezeProcess() 函数详细查看下一小节 5.2 freezeProcess() frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.javaprivate void freezeProcess(final ProcessRecord proc) {int pid proc.getPid(); // Unlocked intentionallyfinal String name proc.processName;final long unfrozenDuration;final boolean frozen;final ProcessCachedOptimizerRecord opt proc.mOptRecord;opt.setPendingFreeze(false);try {// 确认进程是否存在任意的文件锁避免不必要的 free/unfreeze操作// 这是为了防止冻结进程持有文件锁从而引起死锁// 冻结成功之后还会再次确认文件锁如果有锁则立即解冻if (mProcLocksReader.hasFileLocks(pid)) {if (DEBUG_FREEZER) {Slog.d(TAG_AM, name ( pid ) holds file locks, not freezing);}return;}} catch (Exception e) {Slog.e(TAG_AM, Not freezing. Unable to check file locks for name ( pid ): e);return;}synchronized (mProcLock) {pid proc.getPid();// 如果进程没有变成Cached或者不能freeze则退出此次freeze操作if (proc.mState.getCurAdj() ProcessList.CACHED_APP_MIN_ADJ|| opt.shouldNotFreeze()) {return;}// 如果freezer 处于disable状态返回并告知该进程if (mFreezerOverride) {opt.setFreezerOverride(true);return;}// 已经处于frozen或者不是一个应用进程则退出此次 freeze操作// pid为0有可能进程还没有launch完成或者进程被kill了if (pid 0 || opt.isFrozen()) {// Already frozen or not a real process, either one being// launched or one being killedreturn;}Slog.d(TAG_AM, freezing pid name);// 在S版本中将这部分功能提前也是正确的行为// 冻结 binder// 1.如果freezer是使能将同步发送所有的pending 交互给指定的pid// 2.该函数调用后所有的binder 请求都会被block并返回error给发送请求的进程try {if (freezeBinder(pid, true) ! 0) {rescheduleFreeze(proc, outstanding txns);return;}} catch (RuntimeException e) { //如果调用失败则直接kill该进程Slog.e(TAG_AM, Unable to freeze binder for pid name);mFreezeHandler.post(() - {synchronized (mAm) {proc.killLocked(Unable to freeze binder interface,ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true);}});}long unfreezeTime opt.getFreezeUnfreezeTime();//核心函数 setProcessFrozen()同步冻结进程try {Process.setProcessFrozen(pid, proc.uid, true);opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis());opt.setFrozen(true);} catch (Exception e) {Slog.w(TAG_AM, Unable to freeze pid name);}unfrozenDuration opt.getFreezeUnfreezeTime() - unfreezeTime;frozen opt.isFrozen();}if (!frozen) {return;}Slog.d(TAG_AM, froze pid name);// 将此次 freeze 记录到 event log 中EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);// See above for why were not taking mPhenotypeFlagLock hereif (mRandom.nextFloat() mFreezerStatsdSampleRate) {FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED,FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__FREEZE_APP,pid,name,unfrozenDuration);}// 确认在冻结的时候是否收到了 TXNS_PENDING_WHILE_FROZEN的binder请求// 如果有有收到请求则重新freeze 该进程(unfreeze freeze)try {// post-check to prevent racesint freezeInfo getBinderFreezeInfo(pid);if ((freezeInfo TXNS_PENDING_WHILE_FROZEN) ! 0) {synchronized (mProcLock) {rescheduleFreeze(proc, new pending txns);}return;}} catch (RuntimeException e) {Slog.e(TAG_AM, Unable to freeze binder for pid name);mFreezeHandler.post(() - {synchronized (mAm) {proc.killLocked(Unable to freeze binder interface,ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true);}});}try {// 再次check文件锁如果该冻结进程持有文件锁立即unfreezeif (mProcLocksReader.hasFileLocks(pid)) {if (DEBUG_FREEZER) {Slog.d(TAG_AM, name ( pid ) holds file locks, reverting freeze);}unfreezeAppLSP(proc);}} catch (Exception e) {Slog.e(TAG_AM, Unable to check file locks for name ( pid ): e);unfreezeAppLSP(proc);}} 逻辑与R 版本有很大的不同 在冻结进程之前调用 freezeBinder()用以冻结binder 通信在冻结进程之后调用 getBinderFreezeInfo()确认是否在冻结的时候有 TXNS_PENDING_WHILE_FROZEN 的binder 请求如果有该请求则重新freeze 该进程(unfreeze freeze) 弄个流程图理解冻结过程 5.2.1 setProcessFrozen() frameworks/base/core/java/android/os/Process.javapublic static final native void setProcessFrozen(int pid, int uid, boolean frozen); frameworks/base/core/jni/android_util_Process.cppvoid android_os_Process_setProcessFrozen(JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze) {bool success true;if (freeze) {success SetProcessProfiles(uid, pid, {Frozen});} else {success SetProcessProfiles(uid, pid, {Unfrozen});}if (!success) {signalExceptionForGroupError(env, EINVAL, pid);} } 此处的调用在博文《cgroup抽象层》中已经分析过通过接口 SetProcessProfiles() 精细是 SetAttributeAction 类型的profile最终调用 ExecuteForProcess() system/core/libprocesscgroup/task_profiles.cppbool SetAttributeAction::ExecuteForProcess(uid_t, pid_t pid) const {return ExecuteForTask(pid); }bool SetAttributeAction::ExecuteForTask(int tid) const {std::string path;if (!attribute_-GetPathForTask(tid, path)) {LOG(ERROR) Failed to find cgroup for tid tid;return false;}if (!WriteStringToFile(value_, path)) {PLOG(ERROR) Failed to write value_ to path;return false;}return true; } 通过代码需要确定 attribute_-GetPathForTask() system/core/libprocessgroup/task_profiles.cppbool ProfileAttribute::GetPathForTask(int tid, std::string* path) const {std::string subgroup;if (!controller()-GetTaskGroup(tid, subgroup)) {return false;}if (path nullptr) {return true;}if (subgroup.empty()) {*path StringPrintf(%s/%s, controller()-path(), file_name_.c_str());} else {*path StringPrintf(%s/%s/%s, controller()-path(), subgroup.c_str(),file_name_.c_str());}return true; } 有两部分一个是通过 controller 获取subgroup二是进行最终path 的拼接。 下面来看下 congtroller 指向的 GetTaskGroup() system/core/libprocessgroup/cgroup_map.cppbool CgroupController::GetTaskGroup(int tid, std::string* group) const {std::string file_name StringPrintf(/proc/%d/cgroup, tid);std::string content;if (!android::base::ReadFileToString(file_name, content)) {PLOG(ERROR) Failed to read file_name;return false;}// if group is null and tid exists return early because// user is not interested in cgroup membershipif (group nullptr) {return true;}std::string cg_tag;if (version() 2) {cg_tag 0::;} else {cg_tag StringPrintf(:%s:, name());}size_t start_pos content.find(cg_tag);if (start_pos std::string::npos) {return false;}start_pos cg_tag.length() 1; // skip /size_t end_pos content.find(\n, start_pos);if (end_pos std::string::npos) {*group content.substr(start_pos, std::string::npos);} else {*group content.substr(start_pos, end_pos - start_pos);}return true; } 读取 /proc/PID/cgroup 中信息对于 cgroup2读取是 0:: 所在信息在 S 版本中指定的是uid和pid 拼接例如 130|shift:/sys/fs/cgroup # cat /proc/2119/cgroup 4:memory:/ 3:cpuset:/restricted 2:cpu:/foreground 1:blkio:/foreground 0::/uid_10083/pid_2119 最终写的是 /sys/fs/cgroup/uid_xxx/pid_xxx/cgroup.freeze 文件。 某个进程被冻结的旅程图 6. unfreezeAppLSP() frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.javavoid unfreezeAppLSP(ProcessRecord app) {final int pid app.getPid();final ProcessCachedOptimizerRecord opt app.mOptRecord;// 进程已经处于peding freeze中移除冻结消息if (opt.isPendingFreeze()) {// Remove pending DO_FREEZE messagemFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);opt.setPendingFreeze(false);}opt.setFreezerOverride(false);// 如果进程还没有冻结则无需做解冻处理if (!opt.isFrozen()) {return;}// 冻住的进程可以接收异步binder请求但是不会处理只是放入binder buffer 过多的请求会导致buffer耗尽// 这里需要确认下该进程在解冻之前进程是否在冰冻期间收到同步的binder 请求有则kill该进程boolean processKilled false;try {int freezeInfo getBinderFreezeInfo(pid);if ((freezeInfo SYNC_RECEIVED_WHILE_FROZEN) ! 0) {Slog.d(TAG_AM, pid pid app.processName received sync transactions while frozen, killing);app.killLocked(Sync transaction while in frozen state,ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_FREEZER_BINDER_TRANSACTION, true);processKilled true;}if ((freezeInfo ASYNC_RECEIVED_WHILE_FROZEN) ! 0 DEBUG_FREEZER) {Slog.d(TAG_AM, pid pid app.processName received async transactions while frozen);}} catch (Exception e) {Slog.d(TAG_AM, Unable to query binder frozen info for pid pid app.processName . Killing it. Exception: e);app.killLocked(Unable to query binder frozen stats,ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true);processKilled true;}//进程被kill 了无需 unfreezeif (processKilled) {return;}// app.freezeUnfreezeTime记录的是上次free、unfreeze的时间long freezeTime opt.getFreezeUnfreezeTime();try {freezeBinder(pid, false);} catch (RuntimeException e) {Slog.e(TAG_AM, Unable to unfreeze binder for pid app.processName . Killing it);app.killLocked(Unable to unfreeze,ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true);return;}try {Process.setProcessFrozen(pid, app.uid, false);opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis());opt.setFrozen(false);} catch (Exception e) {Slog.e(TAG_AM, Unable to unfreeze pid app.processName . This might cause inconsistency or UI hangs.);}if (!opt.isFrozen()) {Slog.d(TAG_AM, sync unfroze pid app.processName);mFreezeHandler.sendMessage(mFreezeHandler.obtainMessage(REPORT_UNFREEZE_MSG,pid,(int) Math.min(opt.getFreezeUnfreezeTime() - freezeTime, Integer.MAX_VALUE),app.processName));}} 逻辑比较清晰核心处理函数是 setProcessFrozen()详细的流程在上面第 5.2.1 节中已经分析过。 7. kernel 处理 kernel/cgroup/cgroup.cstatic struct cftype cgroup_base_files[] {...{.name cgroup.freeze,.flags CFTYPE_NOT_ON_ROOT,.seq_show cgroup_freeze_show,.write cgroup_freeze_write,},... }; 对 /sys/fs/cgroup/uid_xxx/pid_xxx/cgroup.freeze 文件的写入触发回调函数 cgroup_freeze_write() 函数通过当前的 kernfs 找到对应的 cgroup将这个 cgroup 下所有进程以及子进程都 freeze。 详细的 cgroup_freeze_write() 函数后续将补充剖析。 相关博文 https://justinwei.blog.csdn.net/article/details/131845360 https://justinwei.blog.csdn.net/article/details/131854291  https://justinwei.blog.csdn.net/article/details/131769953 https://justinwei.blog.csdn.net/article/details/131591931 https://justinwei.blog.csdn.net/article/details/131717028 https://justinwei.blog.csdn.net/article/details/131685304 https://justinwei.blog.csdn.net/article/details/131595511
http://www.hkea.cn/news/14560686/

相关文章:

  • 购物类网站首页效果图六盘水做网站
  • 常德制作网站wordpress一键部署
  • 网站建设哪福建省幕墙建设网站要报备吗
  • 网站开发培训费多少钱直通车代运营
  • 网站忘了怎么办啊杭州工业设计
  • 网页设计与制作心得体会1500字页面关键词优化
  • 网站SEO做点提升流量象客美容网站设计
  • 网站备案多久可以注销公共资源交易信息平台
  • 男科医院网站建设wordpress页面居中
  • 一款非常不错的seo网站优化公司源码高端网站建设价格
  • 用php做网站的方法网站建设的公司系统规划
  • 河南省住房和城乡建设局网站企业文化墙素材图片
  • 企业网站源码网站栏目建设征求意见
  • 举报网站怎么做邯郸网站制作个人
  • 网站建设自己wordpress 做笔记
  • 装修网站效果图有了网站怎样做公众号
  • 域名备案网站建设书模板企业网站优化公司有哪些
  • 在自己的网站做百度搜索框怎么自己搭建网站
  • 网站制作五个界面一台主机做两个网站
  • 凤翔网站建设wordpress 离线编辑器
  • vps搭建网站是什么意思建设通电脑版
  • 两学一做知识竞赛网站整站seo定制
  • 网站建设问题及对策关键词分类工具
  • windows2008网站上海的软件外包公司
  • 网站观赏做免费试用的网站
  • 网站开发行业新闻轻云服务器 wordpress
  • 手机介绍网站观澜网站建设公司
  • html网站开发例子东莞网站制作哪家最便宜
  • 四川建设网站信息查询中心网站优化公司电话
  • 上海最好的网站建设金蝶软件有限公司