内存管理-78-低内存-1-危害
一、低内存导致CPU负载高
在 Android 中,系统低内存(Low Memory)与CPU负载高(High CPU Load)之间存在着密切的因果关系。当可用内存不足时,系统为了维持运转和释放空间,会频繁触发一系列底层机制,这些机制往往是极度消耗CPU资源的。
导致这种现象的核心原因主要有以下几个方面:
1. 频繁的垃圾回收(GC)
(1) 触发机制:当 Android App 的堆内存(Heap)接近上限,或者系统整体可用内存极低时,ART(Android Runtime)虚拟机就会频繁触发同步 GC(Concurrent/Explicit GC)。
(2) 高负载原因:为了找出不再使用的对象,GC 线程需要遍历对象树、标记并清理内存。在低内存情况下,GC 触发的频率会指数级上升(俗称“内存抖动”)。GC 线程会长时间占用大量 CPU,导致应用卡顿,甚至引发系统级的 CPU 负载飙升。
2. 内存频繁置换与缺页异常
(1) 触发机制:Linux 内核有一个负责虚拟内存管理的内核线程叫 kswapd。当系统剩余物理内存低于 low 水位线(Watermark)时,kswapd 会被激活。
(2) 高负载原因:
a. ZRAM 压缩解压:当内存不足时,kswapd 会频繁把内存中不常用的页面(Page)通过 LZO/LZ4 等算法压缩后写入 ZRAM;当应用再次需要这些数据时,CPU 又必须实时进行解压。频繁的压缩与解压是典型的 CPU 密集型操作。
b. 文件页换出(Page Cache Eviction):系统会强行回收代码段、资源文件等占用的 Page Cache。当程序运行再次需要这些代码时,会触发主缺页异常(Major Page Fault),系统不得不重新从低速的闪存(UFS/EMMC)中读取数据,这不仅导致 I/O 阻塞,也会让内核态的 CPU 负载显著上升。
3. LMKD的频繁查杀与进程重启
(1) 触发机制:当系统内存进一步恶化,触发了阈值,Android 的 lmkd 守护进程就会开始按照 oom_adj(进程优先级)从低到高的顺序强行杀死后台进程。
(2) 高负载原因:
a. 杀死进程的开销:内核清理进程遗留的内存、句柄、Binder 连接等资源需要消耗 CPU。
b. “杀而复生”的死循环:被杀死的进程中,有很多是常驻后台的服务(如微信、推送服务、系统基础服务)。这些进程被杀后,系统或应用自身会尝试自动重启它们。进程启动时的类加载、初始化、资源配置是极为消耗 CPU 的。这会导致系统陷入“杀死 -> 重启 -> 再被杀 -> 再重启”的恶性循环,使 CPU 长期处于高负载状态。
4. 内存碎片化导致的分配延迟
(1) 触发机制:随着系统运行,内存会被切割得支离破碎。虽然总剩余内存看起来还有,但当应用尝试申请一块连续的大内存(如加载一张大图)时,系统可能找不到足够大的连续空间。
(2) 高负载原因:此时内核会调用 直接内存回收机制(Direct Reclaim) 或是进行 内存整理(Compaction/Migration)。内核需要移动内存中的数据页来拼凑出连续空间,这个移动和重新映射的过程完全由 CPU 在内核态完成,会瞬间拉高 CPU 负载并阻塞当前请求线程。
5. 频繁的 Binder 通信与系统监控开销
(1) 触发机制:在低内存状态下,Android 系统服务(如 ActivityManagerService)需要不断监控各个进程的内存状态,频繁跨进程查询内存快照。
(2) 高负载原因:大量的 dumpsys meminfo 类似操作以及频繁的 Binder IPC 通信,会增加 CPU 在用户态和内核态之间切换(Context Switch)的次数,带来额外的系统负载。
posted on 2026-10-16 21:28 Hello-World3 阅读(14) 评论(0) 收藏 举报
浙公网安备 33010602011771号