
你有没有遇到过这种情况?浏览器开了没一会儿,电脑风扇就开始狂转,打开任务管理器一看,好几个G的内存就这么消失了。这事儿在现在的网页浏览中实在太常见了。
最近,Brave 浏览器的工程师们就盯上了自家产品里的一个“内存大户”——广告拦截器。他们做了一次彻头彻尾的底层重构,成果是内存占用直接砍掉了75%。这可不是什么小打小闹的优化,而是一次教科书级别的技术实践。
广告拦截器为什么这么吃内存?
想象一下,你是一个小区的保安,手里拿着一本厚厚的“黑名单”,上面密密麻麻写着超过10万个不允许进入小区的人名。
每当有人想要进门时,你都必须把这本厚厚的名单从头到尾翻一遍,核对来人的身份。这个过程既慢又耗费体力(内存)。
广告拦截器干的就是这个活儿。
┌─────────────────────────────────────────────────┐
│ 广告拦截器的工作流程 │
├─────────────────────────────────────────────────┤
│ │
│ 网页请求 ──→ 检查 10 万条规则 ──→ 放行/拦截 │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ EasyList │ │
│ │ EasyPrivacy │ │
│ │ uBlock 规则 │ │
│ │ ... 共 10 万+ │ │
│ └───────────────┘ │
│ │
└─────────────────────────────────────────────────┘
Brave 浏览器默认就内置了超过10万条过滤规则。每一条规则都包含了匹配模式、选项标志、元数据等信息。简单做个乘法你就懂了:10万条规则在内存中展开,还没等你打开任何网页,光是加载这个“黑名单”本身,就可能占用高达60MB的内存。
Brave 的内存优化方案:Rust + FlatBuffers
在 Brave 1.85 版本中,一个重大的更新悄然发布:广告拦截引擎的内存占用下降了75%。
这不是什么 JavaScript 的奇技淫巧,也不是延迟加载的花招,而是实打实的底层重构——用 Rust 重写了核心引擎,并配合使用了 FlatBuffers 数据格式。
FlatBuffers 是什么?
我们继续用保安的例子来解释。
以前的做法,是把黑名单印成一本厚厚的书,查人就得一页页翻。而 FlatBuffers 则像把名单做成了一个高效的电子数据库索引,输入名字,结果瞬间就显示出来。
┌─────────────────────────────────────────────────────────┐
│ 传统方式 vs FlatBuffers │
├─────────────────────────────────────────────────────────┤
│ │
│ 传统方式(JSON/对象): │
│ ┌─────────┐ 解析 ┌─────────┐ │
│ │ 原始数据 │ ─────────→ │ 内存对象 │ ← 占用大量内存 │
│ └─────────┘ └─────────┘ │
│ │
│ FlatBuffers: │
│ ┌─────────┐ 直接读取 ┌─────────┐ │
│ │ 二进制块 │ ─────────→ │ 零拷贝访问│ ← 几乎不占额外内存 │
│ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
FlatBuffers 最初是 Google 为游戏引擎开发的,那群人对性能的要求是毫秒级的。它的核心思路就一个字:不复制。
传统的数据格式,比如 JSON,读取时需要先解析,解析完成后要创建对应的对象,这些对象又要存储在堆内存中。一来二去,同一份数据可能在内存里存了好几份副本。
FlatBuffers 不这么干。数据被存储成紧凑的二进制格式,当需要使用时,代码直接从这个原始的二进制数据块中读取所需部分,不创建中间对象,也不进行数据复制。这就是所谓的“零拷贝反序列化”。
为什么要用 Rust?
FlatBuffers 的库支持多种语言,为什么偏偏选择 Rust?答案很简单:为了极致的内存安全。
浏览器是一个高危环境。它每天要处理无数来自不可信互联网的输入数据,稍有不慎就可能被利用导致安全漏洞。据统计,像 Chrome 这样的浏览器,大约 70% 的高危安全漏洞都源于 内存管理 问题。
用 C++ 编写的代码来处理这些不可信的输入,就像一个粗心的人拿着一把锋利的刀切菜,事故只是时间问题。
Rust 则不同。它在编译阶段就通过所有权、借用检查器等机制,将大部分内存安全问题“扼杀在摇篮里”,同时在运行时又没有传统垃圾回收机制带来的开销。
┌─────────────────────────────────────────────────┐
│ 语言特性对比 │
├─────────────────────────────────────────────────┤
│ │
│ C++: │
│ ├── 性能高 │
│ ├── 内存手动管理 │
│ └── 容易出安全漏洞 │
│ │
│ JavaScript: │
│ ├── 开发快 │
│ ├── 有垃圾回收 │
│ └── 性能一般 │
│ │
│ Rust: │
│ ├── 性能高(和 C++ 一个级别) │
│ ├── 编译期内存安全检查 │
│ └── 无垃圾回收开销 │
│ │
└─────────────────────────────────────────────────┘
对于广告拦截器这种需要对每一个 URL 和网络请求进行实时检查的底层组件,既要追求极致的速度,又要确保坚如磐石的安全性,Rust 是目前近乎完美的选择。
内存优化效果
那么,实际效果到底如何呢?数据说明一切。
┌─────────────────────────────────────────────────┐
│ 优化前后对比 │
├─────────────────────────────────────────────────┤
│ │
│ 内存占用: 60 MB ──→ 15 MB (↓ 75%) │
│ │
│ 内存分配: 减少 19%(使用栈分配替代堆分配) │
│ │
│ 用户体验: 页面加载更流畅,风扇转得更少 │
│ │
└─────────────────────────────────────────────────┘
这次重构带来了75%的内存占用下降:
- 10万条规则现在被序列化成一个极其紧凑的 FlatBuffers 二进制块。
- Rust 代码直接读取这个二进制块,无需创建任何中间数据结构对象。
- 在编码上,尽可能使用栈分配而非堆分配,使得总的内存分配调用次数减少了19%。
- 得益于“零拷贝”特性,数据无需复制,直接从原始缓冲区读取。
这意味着,浏览器甚至还没开始加载你的第一个网页,就已经为你省下了45MB的宝贵内存。长时间使用下来,最直观的感受可能就是——电脑风扇确实变得“文静”了许多。
为什么这件事值得关注?
当前的浏览器市场,Chrome 及其 Chromium 内核占据了绝对主导地位。很多浏览器本质上只是给 Chromium 套了个外壳,换了个皮肤。
但 Brave 选择了一条更艰难的路。他们愿意投入资源,去重写这些底层的、用户不易直接感知的组件,目标直指更深层次的内存优化与安全性提升。这种优化可能不会带来炫酷的新功能,但却让浏览体验变得实实在在的更加流畅、稳定。
据悉,Brave 还计划将更多的浏览器组件从 C++ 迁移到 Rust。每一次这样的迁移,都可能带来类似的好处:更低的内存占用、更强的安全性、更少的崩溃。这种用现代、安全语言重构关键系统组件的思路,值得整个软件行业,尤其是开发者 们关注和借鉴。
总结一下
- FlatBuffers 实现了零拷贝反序列化,让数据能直接从二进制块中高效读取,避免了冗余的内存占用。
- Rust 在编译期提供了强大的内存安全保障,同时保证了与 C++ 媲美的运行时性能,且无垃圾回收开销。
- 两者结合,成功将广告拦截规则的内存占用从 60MB 压缩至 15MB,降幅高达75%。
Brave 的这次实践,为浏览器乃至其他高性能、高安全要求的软件优化,树立了一个很好的技术标杆。
想试试看?
Brave 浏览器基于 Chromium 开源项目构建,这意味着你能使用几乎所有 Chrome 扩展。它在隐私保护(如默认阻止跟踪器)和性能优化上显得更为激进。当然,它的一些特性(如内置的加密钱包)可能并非人人需要,界面细节也有提升空间。但如果你正饱受浏览器内存膨胀的困扰,或者格外注重隐私,那么 Brave 这个版本值得你亲自体验一下。
你对浏览器的内存占用有什么看法?平时又用什么方法来解决这个问题呢?欢迎在 云栈社区 与其他技术同好一起交流探讨。