Chromium 与 RAM 的博弈
2025-06-25
“为什么我打开了十个标签页,Chrome 就吃掉了 2GB 内存?”
“Chrome 是不是内存杀手?”
很多用户都会这样吐槽。
从开发者视角,Chromium 是多进程架构,不可避免是个内存消耗大户。
无论什么时候,内存都是稀缺的,C++ 又是一个内存不安全的编程语言。
如何高效、安全地使用内存,是 Chromium 不可避免要去回答的问题。
Chromium 团队有一篇文章:Why we work on memory🔗,解释了为什么要花那么大功夫去处理内存问题。
总结来说有两点:
- 产品角度,内存对于提升用户体验至关重要
- 技术角度,内存优化要兼顾性能(balance a trade-off between performance and memory)
本篇文章不是具体的内存使用指南,而是从一个系统视角(high level),讲述 Chromium 如何利用内存这种稀缺资源。
1. 多进程架构
Chromium 最显著的架构特点,便是: 多进程模型(multi-process architecture),之前的 文章🔗 文章到过多次。
不同的标签页,GPU 模块,网络,都位于不同的进程。
好处不言而喻:
- 安全。不同进程存在等级之分,像标签页进程(render process),权限低,无法主动发起网络请求,这符合 Rule-Of-2🔗 原则。
- 健壮。在操作系统上,不同进程对于资源的使用完全隔离(isolation),其中一个崩溃,不会影响其他进程。
- 高效。不同模块的功能通过进程解耦,结构上更加清晰,而且便于共享,比如共享网络进程。
坏处也有。
内存消耗比较大。
2. 内存分配器
Chromium 的内存,主要分配在以下几个组件:
模块 | 作用 | 内存特征 |
---|---|---|
Blink | 浏览器渲染引擎 | DOM 树、布局树等 |
V8 | JavaScript 执行引擎 | JS 对象、堆、JIT 缓存 |
Skia | 图形渲染引擎 | 绘制缓存、位图等 |
PartitionAlloc | 自研内存分配器 | 控制内存分配粒度、分区隔离 |
其中 PartitionAlloc
是 Chromium 自研的内存分配器,旨在降低碎片、提高速度并增强安全性。
结果🔗 结果明,内存节省高达 22%,响应速度和滚动延迟提高 9%。
3. 内存主动管理
这里主要提两点:V8 和空闲标签页的内存回收。
V8 是 JavaScript 的执行引擎,也是 Chromium 诞生之初的最大卖点。
基于一套在 Blink 上的任务调度系统,V8 实现了在空闲任务中执行垃圾回收的机制,并将其称之为:Getting garbage collection for free🔗。
很多人应该跟我有类似的习惯,同一时刻开几十个标签页。尽管有进程共享机制,仍不可避免会对内存造成一定压力。
于是 Chromium 推出了一个功能:标签页丢弃🔗。
简单讲,就是将很久不再使用的标签页内存暂时释放,腾挪出更多空间给当前正在使用的任务。
可以通过 chrome://discards/ 查看。
4. 分析和监控
任何性能分析的前提,一定是测量(measure)。
Chromium 提供了一系列工具。
-
chrome://memory-internals/
:进程级内存使用 -
chrome://tracing/
:内存快照 + 时间线分析,配合TraceEvent
-
chrome://flags
:启用实验 -
heap profiler
(DevTools): 查看 JS 的内存占用
5. 总结
Chromium 对于内存使用的优化,有很多值得借鉴之处。
我大致总结出三点。
- 隔离和共享。隔离是为了安全,共享是为了高效,没有严格的泾渭分明,边界需要慢慢摸索。
- 分级(hierarchy)。无论内存,还是 CPU、网络等资源,永远稀缺,永远不够用。分级通常是一个兼顾效率和成本的好办法,CPU 可以按照优先级调度,网络请求中可以有多级缓存。
- 可观测性。对于大型系统而言,一个侵入性低、覆盖性广、洞察性深的观测体系,非常重要。
我觉得这套经验,不仅可以用来管理内存,对于钱、时间、注意力的管理,都颇有启发。
(完)
参考
- 本文作者:Plantree
- 本文链接:https://plantree.me/blog/2025/chromium-memory-101/
- 版权声明:所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
最后更新于: 2025-06-26T02:35:16+08:00