解法
在Windows上,内存用尽曾是Firefox崩溃的头号来源,然而许多受影响的用户物理内存还有数GB空闲。Windows限制了应用程序能在RAM加交换文件大小内提交的内存总量,而Firefox无法控制所有消耗该“提交空间”的部分:显卡驱动提交用于纹理的内存大部分时候用不到,但仍计入限制。多年来Firefox一直削减自身内存使用并监控回退,但这些努力都没有像后来的技巧那样对崩溃率产生显著影响。
面对分配无法满足,惯常做法是放弃:多数失败路径没有合理的继续方式,因此浏览器以受控方式崩溃。这相当于将提交空间上限看作固定不变,但Windows上并非如此——当交换文件接近满时,操作系统会自动增大,从而扩展应用能提交的内存。
Mozilla的做法是让主进程在分配失败时短暂等待然后重试,给Windows扩展页面文件的时间。这段停顿还有别的好处:Firefox以多进程方式运行,除了主进程外失去任何其他进程都能存活,所以延迟期间,内存失控的内容或GPU进程往往先崩溃,从而腾出空间让浏览器恢复。丢一个网页或闪断一下好过整个浏览器崩溃。
这个技巧在Firefox 105中上线,将每小时活跃使用中浏览器OOM崩溃减少了超过70%,远好于Mozilla最乐观的预测。团队在Firefox安卓版和Firefox OS上用过同样方法,并且在内存压力下标签页崩溃略有上升,这是他们接下来要着手压低的。
What it achieved
在Windows上分配失败不一定是致命的——操作系统按需扩展页面文件,因此等待并重试能把内存耗尽崩溃变成短暂卡顿。
为什么有效
Windows不会杀掉分配失败的应用程序——调用会返回错误,因此进程可以选择等待重试而不是退出。
提交空间上限是可扩展的:交换文件接近满时Windows会自动增大,短暂停顿给它时间扩张。
Firefox的多进程设计让主进程停顿的同时,可重载的内容或GPU进程先内存溢出并释放内存,从而保护整个浏览器。
此项改动改变的是失败处理而非内存使用,因此一个小修复胜过多年减少体积的努力。
可以借鉴什么
当平台能按需扩展资源时,失败选择等待而非崩溃;多进程应用中让可重载子进程先吸收伤害。
后续
Firefox 105在2022年9月上线了等待并重试行为,遥测数据显示每活跃使用小时浏览器OOM崩溃减少了超70%,“远超我们最乐观预测”。这卡顿也导致了标签页崩溃略有上升,团队随后着手削减,同时Mozilla开始区分低提交空间和低物理内存,以便Firefox差异化应对,减少交换。工程师Raymond Kraesig实现了该技巧并跟踪影响;类似方法在Firefox安卓版和Firefox OS上已成功应用。
从这里,追溯依据
参考来源
- Improving Firefox stability with this one weird trick hacks.mozilla.org
- Hacker News discussion: Improving Firefox stability with this one weird trick news.ycombinator.com