解决macOS系统磁盘空间突然占满并卡顿的问题

现象

有时macOS会发生突然的卡顿问题,同时会有提示说磁盘剩余空间不足。按照过去,一般解决这种问题的方法就是直接重启机器。这种方法虽然能解决问题,但还是不得不面对重启后部分应用状态被重置的问题。能不能做到不重启就能解决这个问题呢?

探究

在经历过数次类似问题后,我在机器很卡的情况下仍然运行了磁盘占用分析工具,首先发现了磁盘空间占用是由/private/var/vm/swapfile*这一系列前缀相同的文件所占据的。那么这些文件具体是什么作用呢? 通过名字就能看出是交换文件,承担了虚拟内存功能。我的机器是256G的磁盘,平时空闲空间在40~50G,问题发生时一般这些文件后面的编号都能到三四十。通过观察活动监视器的内存面板,能够发现这些文件的数量和”已使用的交换”是能够对应的上的。而交换区是如何占据的呢? 自然是由于进程占用内存,但是被换出导致。那其实只要找到内存分配超多的进程,结束掉之后减少交换区的占用,系统理应能够释放这些交换空间。

但是现实和理想是有差距的。从10.14开始其实我就发现了这个机制,但是当时的清理掉占据大量交换空间的进程后,交换文件个数并没有减少。

随着系统更新到10.15.7,某一次我终于抓住了机会,在出现磁盘空间低的时候,打开活动监视器,发现是”通知中心”进程无响应,并且占据了25G的内存,其中24G被交换出去,加上其他进程被挤出去了10个多G的内存,所以总共有34G交换空间被占用。此时结束掉”通知中心”进程,发现交换文件被删掉了很多,剩下了大概十个交换文件。但是看后缀,并不是后创建的被删除,后缀34的交换文件还留着,中间的基本都被删没了。接下来我又主动结束掉了占用交换空间较大的进程并重新启动应用,最终交换空间占用大概保持在6G左右。这里还发现一个事情。10.15.7下有一个比较好的机制,貌似是交换文件的使用率有了优化,比如关掉了大量占据交空间的进程后,不会因为出现较为稀疏的内存页面映射而导致大量的交换文件不能被删除,也就是10.14时代的问题。

有兴趣的可以研究下 xnu的源码,参照 这个大佬的书 的最新版应该有比较详细的关于vm部分的讲解。但是现在网上能看到的都是旧版,写的时候还没有引入内存压缩,而旧版里描述实际管理swapfile文件的dynamic_pager工具在system_cmds源码 中也发生了很大的变化,不再负责实际的swapfile文件管理。

方案

那么总结一下方案。就是如果系统提示突然的磁盘空间低,此时打开活动监视器,点击内存选项卡,按照内存占用排序,从高到低开始结束进程即可。一般都是由于某些进程的线程发生了死锁导致了资源不能正常释放或一直在申请,导致占用内存过高。结束掉后,观察交换空间占用显著下降,磁盘空间开始恢复,即完成处理。