Chromium 与 RAM 的博弈

2025-06-25 pv

“为什么我打开了十个标签页,Chrome 就吃掉了 2GB 内存?”

“Chrome 是不是内存杀手?”

很多用户都会这样吐槽。

从开发者视角,Chromium 是多进程架构,不可避免是个内存消耗大户。

无论什么时候,内存都是稀缺的,C++ 又是一个内存不安全的编程语言。

如何高效、安全地使用内存,是 Chromium 不可避免要去回答的问题。

Chromium 团队有一篇文章:Why we work on memory🔗,解释了为什么要花那么大功夫去处理内存问题。

总结来说有两点:

  1. 产品角度,内存对于提升用户体验至关重要
  2. 技术角度,内存优化要兼顾性能(balance a trade-off between performance and memory)

本篇文章不是具体的内存使用指南,而是从一个系统视角(high level),讲述 Chromium 如何利用内存这种稀缺资源

1. 多进程架构

Chromium 最显著的架构特点,便是: 多进程模型(multi-process architecture),之前的 文章🔗 文章到过多次。

不同的标签页,GPU 模块,网络,都位于不同的进程。

好处不言而喻:

  1. 安全。不同进程存在等级之分,像标签页进程(render process),权限低,无法主动发起网络请求,这符合 Rule-Of-2🔗 原则。
  2. 健壮。在操作系统上,不同进程对于资源的使用完全隔离(isolation),其中一个崩溃,不会影响其他进程。
  3. 高效。不同模块的功能通过进程解耦,结构上更加清晰,而且便于共享,比如共享网络进程。

坏处也有。

内存消耗比较大

2. 内存分配器

Chromium 的内存,主要分配在以下几个组件:

模块作用内存特征
Blink浏览器渲染引擎DOM 树、布局树等
V8JavaScript 执行引擎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 对于内存使用的优化,有很多值得借鉴之处。

我大致总结出三点。

  1. 隔离和共享。隔离是为了安全,共享是为了高效,没有严格的泾渭分明,边界需要慢慢摸索。
  2. 分级(hierarchy)。无论内存,还是 CPU、网络等资源,永远稀缺,永远不够用。分级通常是一个兼顾效率和成本的好办法,CPU 可以按照优先级调度,网络请求中可以有多级缓存。
  3. 可观测性。对于大型系统而言,一个侵入性低、覆盖性广、洞察性深的观测体系,非常重要。

我觉得这套经验,不仅可以用来管理内存,对于钱、时间、注意力的管理,都颇有启发

(完)

参考

  1. Why we work on memory - Google Docs🔗
  2. Chromium Docs - Key Concepts in Chrome Memory🔗
  3. PartitionAlloc Design🔗
  4. Tab Discarding in Chrome - A Memory-Saving Experiment | Blog | Chrome for Developers🔗
在 GitHub 上编辑本页面

最后更新于: 2025-06-26T02:35:16+08:00