版本基于:Android S 0. 前言 Android Q 中新增了framework 端app 内存回收优化方案。当app 的 oom adj 发生特定变化时,framework 端会对应用的内存进行处理。随着版本的演变,这部分优化
版本基于:Android S
Android Q 中新增了framework 端app 内存回收优化方案。当app 的 oom adj 发生特定变化时,framework 端会对应用的内存进行处理。随着版本的演变,这部分优化工作也一直在完善,笔者将针对 Android R 和 Android S 对该部分的优化流程分别进行详细地剖析。
在上一文中,针对Android R 版本进行了详细的剖析,本文继续剖析 Android S 版本。
注意:
本文中提到的 “压缩” 这个词,其实指的是内存回收优化,因为只有到确切的逻辑的时候才明确到底是匿名页回收还是文件页回收,而在此之前我们暂定为 compact 处理。
另外,本文分析是对比于 Android R 版本,最后也会总结下两个版本之间的差异和优缺点。
App 端的内存压缩管理是在 CachedAppOptimizer 类中完成。
我们在之前的博文《oom_adj 更新原理(1)》、《oom_adj 更新原理(2)》中得知 AMS 通过 OomAdjuster 类来管理 oom_adj 的更新、计算、应用。在 OomAdjuster 中也实例了一个 CachedAppOptimizer 的对象:
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, ServiceThread adjusterThread) { mService = service; ... mCachedAppOptimizer = new CachedAppOptimizer(mService); ... }
参数为 AMS 对象。
下面来看下 CachedAppOptimizer 构造:
frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.java public CachedAppOptimizer(ActivityManagerService am) { this(am, null, new DefaultProcessDependencies()); } @VisibleForTesting CachedAppOptimizer(ActivityManagerService am, PropertyChangedCallbackForTest callback, ProcessDependencies processDependencies) { mAm = am; mProcLock = am.mProcLock; mCachedAppOptimizerThread = new ServiceThread("CachedAppOptimizerThread", mCompactionPriority, true); mProcStateThrottle = new HashSet<>(); mProcessDependencies = processDependencies; mTestCallback = callback; mSettingsObserver = new SettingsContentObserver(); mProcLocksReader = new ProcLocksReader(); }
构造中创建了一个 ServiceThread,名称为 CachedAppOptimizerThread,优先级为THREAD_GROUP_SYSTEM。
mProcessDependencies 是 DefaultProcessDependencies类型的对象,用以最后的压缩处理。
与 Android R 差异的地方:
不同于 Android R 版本,Android R 中 的 init() 函数是在 SystemServer.startOtherServices() 的时候调用 AMS 中installSystemProviders() 函数触发,在 installSystemProviders() 会调用 mOomAdjuster.initSettings()。
而Android S 中 installSystemProviders() 被定义在 ContentProviderHelper.java 中。
在 OomAdjuster.initSettings() 中会调用到 CachedAppOptimizer.init()。
frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.java public void init() { DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener); 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) { updateUseCompaction(); updateCompactionActions(); updateCompactionThrottles(); updateCompactStatsdSampleRate(); updateFreezerStatsdSampleRate(); updateFullRssThrottle(); updateFullDeltaRssThrottle(); updateProcStateThrottle(); updateUseFreezer(); updateMinOomAdjThrottle(); updateMaxOomAdjThrottle(); } }
相比于Android R 这里多了个针对冻结属性的监听 mOnNativeBootFlagsChangedListener;
另外,在最后多了两个 update 函数。
private void updateUseCompaction() { mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION); mCompactionPriority = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACTION_PRIORITY, Process.THREAD_GROUP_BACKGROUND); if (mUseCompaction && mCompactionHandler == null) { if (!mCachedAppOptimizerThread.isAlive()) { mCachedAppOptimizerThread.start(); } mCompactionHandler = new MemCompactionHandler(); } Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(), mCompactionPriority); }
相比较 Android R,这里将 thread 的优先级进行了动态配置,优先级可以通过 DeviceConfig 的 compaction_priority 属性设置。另外,优先级的设置也不依赖 mUsecompaction 是否使能。
其他与R 都相同,首先获取下属性 use_compaction,默认值使用 DEFAULT_USE_COMPACTION (false):
@VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
如果 user_compation 使能,接着就会创建 mCompactionHandler 用以异步消息处理,并且启动在构造函数中创建的ServiceThread。
来看下 MemCompactionHandler 类:
private final class MemCompactionHandler extends Handler { private MemCompactionHandler() { super(mCachedAppOptimizerThread.getLooper()); } @Override public void handleMessage(Message msg) { switch (msg.what) { case COMPACT_PROCESS_MSG: { ... break; } case COMPACT_SYSTEM_MSG: { ... break; } } }
Looper 是用的就是 ServiceThread 的Looper,主要用以处理压缩进程内存或system 进程内存。
private void updateCompactionActions() { int compactAction1 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_ACTION_1, DEFAULT_COMPACT_ACTION_1); int compactAction2 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_ACTION_2, DEFAULT_COMPACT_ACTION_2); mCompactActionSome = compactActionIntToString(compactAction1); mCompactActionFull = compactActionIntToString(compactAction2); }
private void updateCompactionThrottles() { boolean useThrottleDefaults = false; // TODO: improve efficiency by calling DeviceConfig only once for all flags. String throttleSomeSomeFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_1); String throttleSomeFullFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_2); String throttleFullSomeFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_3); String throttleFullFullFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_4); String throttleBFGSFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_5); String throttlePersistentFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_6); String throttleMinOomAdjFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_MIN_OOM_ADJ); String throttleMaxOomAdjFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_MAX_OOM_ADJ); if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag) || TextUtils.isEmpty(throttleFullSomeFlag) || TextUtils.isEmpty(throttleFullFullFlag) || TextUtils.isEmpty(throttleBFGSFlag) || TextUtils.isEmpty(throttlePersistentFlag) || TextUtils.isEmpty(throttleMinOomAdjFlag) || TextUtils.isEmpty(throttleMaxOomAdjFlag)) { // Set defaults for all if any are not set. useThrottleDefaults = true; } else { try { mCompactThrottleSomeSome = Integer.parseInt(throttleSomeSomeFlag); mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag); mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag); mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); mCompactThrottleMinOomAdj = Long.parseLong(throttleMinOomAdjFlag); mCompactThrottleMaxOomAdj = Long.parseLong(throttleMaxOomAdjFlag); } catch (NumberFORMatException e) { useThrottleDefaults = true; } } if (useThrottleDefaults) { mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1; mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2; mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3; mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ; mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ; } }
相比较 Android R,主要这里多了两个针对 adj 的限制值:mCompactThrottleMinOomAdj 和 mCompactThrottleMaxOomAdj。当以 FULL 进行 compact 时,需要上一次的 oom_adj 不是 cached。在 R 版本中 这些条件判断放在 OomAdjuster.applyOomAdjLocked() 函数中,而在 S 版本中将其放到了这里。笔者猜想,这样设计的初衷,本应该是为了让用户对 FULL 压缩的 adj 达到可控,但相比较 applyOomAdjLSP() 函数,还是Android R 更好一些。
private void updateFullRssThrottle() { mFullAnonRssThrottleKb = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_FULL_RSS_THROTTLE_KB, DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB); // Don't allow negative values. 0 means don't apply the throttle. if (mFullAnonRssThrottleKb < 0) { mFullAnonRssThrottleKb = DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB; } }
private void updateFullDeltaRssThrottle() { mFullDeltaRssThrottleKb = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB); if (mFullDeltaRssThrottleKb < 0) { mFullDeltaRssThrottleKb = DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB; } }
private void updateProcStateThrottle() { String procStateThrottleString = DeviceConfig.getString( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_PROC_STATE_THROTTLE, DEFAULT_COMPACT_PROC_STATE_THROTTLE); if (!parseProcStateThrottle(procStateThrottleString)) { Slog.w(TAG_AM, "Unable to parse app compact proc state throttle \"" + procStateThrottleString + "\" falling back to default."); if (!parseProcStateThrottle(DEFAULT_COMPACT_PROC_STATE_THROTTLE)) { Slog.wtf(TAG_AM, "Unable to parse default app compact proc state throttle " + DEFAULT_COMPACT_PROC_STATE_THROTTLE); } } }
进程冻结状态初始化,后续将单独剖析下冻结优化。
private void updateMinOomAdjThrottle() { mCompactThrottleMinOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_MIN_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ); // Should only compact cached processes. if (mCompactThrottleMinOomAdj < ProcessList.CACHED_APP_MIN_ADJ) { mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ; } } private void updateMaxOomAdjThrottle() { mCompactThrottleMaxOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_MAX_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ); // Should only compact cached processes. if (mCompactThrottleMaxOomAdj > ProcessList.CACHED_APP_MAX_ADJ) { mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ; } }
这两个函数是 Android S 多出来的,主要是针对 FULL 压缩时判断。
压缩优化的触发分多种情形,在 CachedAppOptimizer 中,压缩优化发起者主要有:
重要逻辑,与Android R 版本类似,本文主要剖析下前两个函数。
在 OomAdjuster.applyOomAdjLSP() 触发:
private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, long nowElapsed) { ... if (mCachedAppOptimizer.useCompaction() && mService.mBooted) { // Cached and prev/home compaction if (state.getCurAdj() != state.getSetAdj()) { // Perform a minor compaction when a perceptible app becomes the prev/home app // Perform a major compaction when any app enters cached // reminder: here, setAdj is previous state, curAdj is upcoming state if (state.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ|| state.getCurAdj() == ProcessList.HOME_APP_ADJ)) { mCachedAppOptimizer.compactAppSome(app); } else if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) { mCachedAppOptimizer.compactAppFull(app); } } else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE && state.getSetAdj() < ProcessList.FOREGROUND_APP_ADJ // Because these can fire independent of oom_adj/procstate changes, we need // to throttle the actual dispatch of these requests in addition to the // processing of the requests. As a result, there is throttling both here // and in CachedAppOptimizer. && mCachedAppOptimizer.shouldCompactPersistent(app, now)) { mCachedAppOptimizer.compactAppPersistent(app); } else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE && state.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE && mCachedAppOptimizer.shouldCompactBFGS(app, now)) { mCachedAppOptimizer.compactAppBfgs(app); } } ... }
相比较 Andoird R 版本,这里对 FULL 压缩进行了逻辑调整,把R 中 从 非 cached 到 cached 的判断,改成了这里只关心目前处于 cached,然后在 compactAppFull() 中再进行确认。笔者认为这样索性将条件完全交给 compactAppFull() 好了啊,不清楚设计的目的。
逻辑剖析这里就省略了,详细可以查看 Android R 版本。
void compactAppSome(ProcessRecord app) { app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_SOME); if (!app.mOptRecord.hasPendinGCompact()) { app.mOptRecord.setHasPendingCompact(true); mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState())); } }
相比较 Android R,ProcessRecord 类中多加了一个 mOptRecord 的成员变量,类型为
ProcessCachedOptimizerRecord,就是为了配合 CachedAppOptimizer 类。
其他逻辑上跟Android R 相同。
void compactAppFull(ProcessRecord app) { // Apply OOM adj score throttle for Full App Compaction. if ((app.mState.getSetAdj() < mCompactThrottleMinOomAdj || app.mState.getSetAdj() > mCompactThrottleMaxOomAdj) && app.mState.getCurAdj() >= mCompactThrottleMinOomAdj && app.mState.getCurAdj() <= mCompactThrottleMaxOomAdj) { app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL); if (!app.mOptRecord.hasPendingCompact()) { app.mOptRecord.setHasPendingCompact(true); mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState())); } } else { if (DEBUG_COMPACTION) { Slog.d(TAG_AM, "Skipping full compaction for " + app.processName + " oom adj score changed from " + app.mState.getSetAdj() + " to " + app.mState.getCurAdj()); } } }
如 3.1 节所述,这里多加了条件判断。
消息处理的逻辑位于 MemCompactionHandler.handleMessage()函数,逻辑基本上与 Android R 版本相同,这里不做过多剖析。
需要注意的是两个地方:
public void performCompaction(String action, int pid) throws IOException { if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FULL])) { compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG); } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FILE])) { compactProcess(pid, COMPACT_ACTION_FILE_FLAG); } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_ANON])) { compactProcess(pid, COMPACT_ACTION_ANON_FLAG); } }
与Android R 版本不同,这里调用了 native 的接口:
static private native void compactProcess(int pid, int compactionFlags);
frameworks/base/services/core/jni/com_android_server_am_CachedAppOptimizer.cppstatic void com_android_server_am_CachedAppOptimizer_compactProcess(JNIEnv*, jobject, jint pid, jint compactionFlags) { compactProcessOrFallback(pid, compactionFlags);}
---->
frameworks/base/services/core/jni/com_android_server_am_CachedAppOptimizer.cppstatic void compactProcessOrFallback(int pid, int compactionFlags) { // 入参compactionFlags 必须是ANON_FLAG 或 FILE_FLAG中的一种或两种 if ((compactionFlags & (COMPACT_ACTION_ANON_FLAG | COMPACT_ACTION_FILE_FLAG)) == 0) return; // 确认是否有 anon 页回收,还是有file 页回收 bool compactAnon = compactionFlags & COMPACT_ACTION_ANON_FLAG; bool compactFile = compactionFlags & COMPACT_ACTION_FILE_FLAG; // Set when the system does not support process_madvise syscall to avoid // gathering VMAs in subsequent calls prior to falling back to procfs static bool shouldForceProcFs = false; std::string compactionType; VmaToAdviseFunc vmaToAdviseFunc; // 根据压缩action,确认compactionType 和 回调函数 // 回调函数后面会调用到,主要返回 process_madvise() 所需要的类型 MADV_COLD 或MADV_PAGEOUT if (compactAnon) { if (compactFile) { compactionType = "all"; vmaToAdviseFunc = getAnyPageAdvice; } else { compactionType = "anon"; vmaToAdviseFunc = getAnonPageAdvice; } } else { compactionType = "file"; vmaToAdviseFunc = getFilePageAdvice; } // 如果compactProcess() 失败,即系统不支持 process_madvise()系统调用时, // 通过shouldForceProcFs 变量控制,强制走 proc/PID/reclaim 节点驱动 if (shouldForceProcFs || compactProcess(pid, vmaToAdviseFunc) == -ENOSYS) { shouldForceProcFs = true; compactProcessProcfs(pid, compactionType); }}
---->
frameworks/base/services/core/jni/com_android_server_am_CachedAppOptimizer.cppstatic int64_t compactProcess(int pid, VmaToAdviseFunc vmaToAdviseFunc) { ProcMemInfo meminfo(pid); std::vector pageoutVmas, coldVmas; auto vMacollectorCb = [&coldVmas,&pageoutVmas,&vmaToAdviseFunc](const Vma& vma) { int advice = vmaToAdviseFunc(vma); //通过回调确定madvise的类型MADV_PAGEOUT或MADV_COLD switch (advice) { case MADV_COLD: coldVmas.push_back(vma); break; case MADV_PAGEOUT: pageoutVmas.push_back(vma); break; } }; // 读取 /proc/PID/maps 确定vma并调用回调函数 vmaClooectorCb meminfo.ForEachVmaFromMaps(vmaCollectorCb); // 对进程中统计出来的 pageoutVma 进行 MADV_PAGEOUT 处理 int64_t pageoutBytes = compactMemory(pageoutVmas, pid, MADV_PAGEOUT); if (pageoutBytes < 0) { // Error, just forward it. return pageoutBytes; } // 对进程中统计出来的 coldVma 进行MADV_COLD处理 int64_t coldBytes = compactMemory(coldVmas, pid, MADV_COLD); if (coldBytes < 0) { // Error, just forward it. return coldBytes; } return pageoutBytes + coldBytes;}
---->
frameworks/base/services/core/jni/com_android_server_am_CachedAppOptimizer.cppstatic int64_t compactMemory(const std::vector& vmas, int pid, int madviseType) { // UIO_MAXIOV is currently a small value and we might have more addresses // we do multiple syscalls if we exceed its maximum static struct iovec vmasToKernel[UIO_MAXIOV]; if (vmas.empty()) { return 0; } unique_fd pidfd(pidfd_open(pid, 0)); if (pidfd < 0) { // Skip compaction if failed to open pidfd with any error return -errno; } int64_t totalBytesCompacted = 0; for (int iBase = 0; iBase < vmas.size(); iBase += UIO_MAXIOV) { int totalVmasToKernel = std::min(UIO_MAXIOV, (int)(vmas.size() - iBase)); for (int iVec = 0, iVma = iBase; iVec < totalVmasToKernel; ++iVec, ++iVma) { vmasToKernel[iVec].iov_base = (void*)vmas[iVma].start; vmasToKernel[iVec].iov_len = vmas[iVma].end - vmas[iVma].start; } auto bytesCompacted = process_madvise(pidfd, vmasToKernel, totalVmasToKernel, madviseType, 0); if (CC_UNLIKELY(bytesCompacted == -1)) { return -errno; } totalBytesCompacted += bytesCompacted; } return totalBytesCompacted;}
最终使用 process_madvise() 对每个vma 进行处理。
frameworks/base/services/core/jni/com_android_server_am_CachedAppOptimizer.cppstatic void com_android_server_am_CachedAppOptimizer_compactSystem(JNIEnv *, jobject) { std::unique_ptr proc(opendir("/proc"), closedir); struct dirent* current; while ((current = readdir(proc.get()))) { if (current->d_type != DT_DIR) { continue; } // don't compact system_server, rely on persistent compaction during screen off // in order to avoid mmap_sem-related stalls if (atoi(current->d_name) == getpid()) { continue; } std::string status_name = StringPrintf("/proc/%s/status", current->d_name); struct stat status_info; if (stat(status_name.c_str(), &status_info) != 0) { // must be some other directory that isn't a pid continue; } // android.os.Process.FIRST_APPLICATION_UID if (status_info.st_uid >= 10000) { continue; } int pid = atoi(current->d_name); compactProcessOrFallback(pid, COMPACT_ACTION_ANON_FLAG | COMPACT_ACTION_FILE_FLAG); }}
最终调用的也是 compactProcessOrFallback() 函数。
bionic/libc/include/sys/mman.hssize_t process_madvise(int picfd, const struct iovec* iovec, size_t vlen, int advice, unsigned flags);
process_madvise() 这个系统调用用于 kernel 关于进程地址区域的处理给出建议或方向。
需要支持 linux 5.10 版本;
这些建议目的是为了提高系统或应用的性能。
地址区域通过结构体 iovec 和 vlen 管理。
参数:
详细的内核调用这里就不过多剖析,都是调用 walk_page_range(),walk_ops 也都是 cold_walk_ops,但根据 advise 不同,逻辑略微偏差,就是 deactivate 和reclaim 逻辑。
至此,Android S 版本中关于 app 回收优化就全部剖析完成,下面做个总结:
关于Andoid R版本的压缩优化,可以查看上一篇博文。
参考:
https://man7.org/linux/man-pages/man2/process_madvise.2.html
https://man7.org/linux/man-pages/man2/madvise.2.html
https://justinwei.blog.csdn.net/article/details/131591931
来源地址:https://blog.csdn.net/jingerppp/article/details/131769953
--结束END--
本文标题: Android 中app内存回收优化(二):S 版本
本文链接: https://lsjlt.com/news/402064.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0