从 base 出发:深入理解 Chromium 自研基础库的体系结构与设计哲学(兼谈为什么不直接用 STL)

一、背景:一个跨平台浏览器为什么要重新造“轮子”?

在浏览器开发生态里,Chromium 是当之无愧的“核心内核”。无论是 Google Chrome、Edge、360、Brave,还是大量国产定制浏览器,它们的技术底座几乎都源自 Chromium。

从表面上看,我们很容易把精力放在渲染引擎(Blink)、进程模型、网络模块、Media Pipeline 等“看起来很硬核”的模块上,而忽略掉内核最底层的基础设施 —— base 库

事实上,如果没有 base 这一层打底,Chromium 很多模块(包括线程系统、IPC 框架甚至 task 调度模型)根本无法运行。
更重要的是,标准 C++ STL 或 Boost 并不能满足 Chromium 巨型跨平台架构在一致性、性能和可维护性上的要求,这也是它“重新造轮子”的根本原因。

本文将从源码层面出发,带你完整理解 base 库是什么、解决了什么问题、主要模块组成、核心设计理念、实际开发场景,以及它的独特价值,希望可以成为你学习 Chromium 内核体系的一个“起始点”。


二、base 库是什么?

2.1 定位

base 是 Chromium 的最底层、最通用的公共库,它 不依赖任何其他模块 却被其他所有模块依赖(net/content/chrome/gin/v8...)。

它提供的是:

  • 通用跨平台工具类(字符串、时间、文件、进程)

  • 线程、任务、事件循环

  • 内存管理封装(智能指针、引用计数、弱指针)

  • 基础容器、安全格式化、日志框架

  • 方便浏览器使用的观察者模式 / callback / Bind

换句话说,它相当于一个大型 C++ 工具库,针对浏览器场景做过深度裁剪与优化

2.2 为什么不是直接用 STL?
标准库 / BoostChromium 需求
行为在不同 OS 上实现不同需要跨平台行为绝对一致
缺乏线程模型 / 消息循环浏览器大量依赖异步任务
debug 模式性能很差(特别是多线程容器)大型项目开发期间大量使用 debug 构建
部分 API 不支持 UTF-8 字符处理浏览器要处理全球语言
很难对每个细节打补丁Chromium 要求所有基础能力可控

✅ 所以 base 是一种“巨大工程规模 + 跨平台一致性 + 高性能可控”的折中解决方案
❌ 它不是为了“重复造轮子”而造轮子


三、整体结构全览

从功能层面,base 可以大致划成下面几个子域:

功能域典型文件夹 / 类
智能指针与内存memory/(RefCounted、WeakPtr、scoped_refptr)
线程 & 任务调度threading/(Thread、ThreadPool、TaskRunner)
消息循环message_loop/(MessageLoop、RunLoop)
字符串处理strings/(UTF8→UTF16、string_util)
容器containers/(flat_map、circular_deque)
时间日期time/(Time、TimeDelta、Timer)
文件系统files/(File、FilePath、FileUtil)
日志logging/(LOG/ CHECK/ DCHECK)
JSONjson/(base::Value、JSONReader/Writer)
观察者observer_list.h / ObserverListThreadSafe
系统/进程信息process/sys_info/
数据统计metrics/(Histogram、UMA)
IPC/SOCKETsync_socket/

下面我们从几个关键子模块深入展开。


四、核心子模块分析

4.1 memory:智能指针、引用计数、WeakPtr

Chromium 拒绝使用裸指针,因此 base 提供了三种常用内存管理手段:

典型用途
RefCounted引用计数对象,适用于跨线程共享资源
WeakPtr避免异步回调中访问已销毁对象
scoped_refptr智能指针封装,对应 RefCounted 对象

例如常见写法:

class MyObject : public base::RefCounted<MyObject> { public: void DoSomething(); private: friend class base::RefCounted<MyObject>; ~MyObject() = default; }; // 使用 scoped_refptr<MyObject> obj = new MyObject();

⚠️ 注意:WeakPtr 必须配合 base::WeakPtrFactory 使用,且只能在创建它的线程销毁。


4.2 threading + message_loop:线程模型与事件分发

Chromium 并不是简单的 “pthread + sleep”,而是实现了一整套可扩展的异步执行模型,其中最核心的是:

模块功能
base::Thread创建一个有自己 MessageLoop 的线程
TaskRunner提供任务投递接口(PostTask / PostDelayedTask)
MessageLoop事件循环 + 消息调度
ThreadPool全局线程池(后台执行任务)

典型使用:

base::Thread my_thread("MyThread"); my_thread.Start(); scoped_refptr<base::TaskRunner> task_runner = my_thread.task_runner(); task_runner->PostTask(FROM_HERE, base::BindOnce(&Foo));

这套机制贯穿于整个浏览器生命周期(I/O 线程 / UI 线程 / DB 线程 / GPU 线程 都是由 base 启动和管理的)。


4.3 containers:自研轻量容器

Chromium 没有完全摒弃 STL,但对以下场景重新实现容器,以提升性能:

base 容器优势与场景
flat_map基于排序数组实现,查询快,内存连续,适合小规模 KV
circular_deque环形缓冲区,频繁入队出队性能好
stack_container小对象直接放在栈上,避免 heap 分配

例如 flat_map 效果如下:

base::flat_map<std::string, int> m = {{"a",1}, {"b",2}};

性能上在 50 个元素以内比 std::map 快很多。


4.4 files & path & sys_info
  • FilePath 专门处理不同平台的目录分隔符

  • ReadFileToString() / WriteFile() 提供统一接口

  • SysInfo::AmountOfPhysicalMemory() 返回系统内存
    → 行为在 Windows / Linux / macOS 上完全一致


4.5 logging 与 CHECK/DCHECK

在 Chromium 项目中你会非常频繁地见到这些宏:

LOG(INFO) << "Something happened"; CHECK(condition); DCHECK(ptr != nullptr);

区别:

含义
LOG始终启用的日志
CHECK失败直接崩溃(发布版本也有效)
DCHECK仅在 Debug 构建中有效

五、设计哲学总结

关键词表现
跨平台一致性所有模块对不同 OS 做统一抽象(FilePath / SysInfo / Thread)
性能可控自研容器 / 回收机制 / 减少 STL 波动带来的抖动
适配浏览器模型专门的 MessageLoop + TaskRunner 支撑多进程异步调度
长期可维护性统一宏 / 接口风格 / 智能指针规范

这也是为什么“base” 被视作浏览器内核的“地基”。越往上的模块越轻,但它必须足够稳固,否则整个架构就会崩。


六、在实际开发中的典型使用场景

场景base 中对应功能
跨线程投递任务PostTask(FROM_HERE,...)
延迟或重复任务base::Timer / base::RepeatingTimer
安全字符串拼接base::StringPrintf
JSON 配置加载base::JSONReader::Read()
系统级信息(CPU/内存)base::SysInfo
多线程日志调试LOG(…) << …;
避免异步回调悬空base::WeakPtr + WeakPtrFactory

七、如何进一步阅读 base 源码(推荐阅读路径)

步骤模块目标
base/memory理解 RefCounted、WeakPtr 实现和引用模型
base/threading阅读 Thread/ThreadPool/TaskRunner 工作流程
base/message_loop异步事件循环扩展(MsgPump 、MessageLoop::Run)
base/containers感受自研容器设计思路
base/logging日志系统实现,理解 CHECK/DCHECK crash 流程
base/task宏观理解整个 TaskScheduler 如何在浏览器内分发任务

📌 建议结合一个实际页面 WebUI 逻辑,例如 chrome://version,反着追踪它用到的 base API,会更快建立“感知能力”。


八、总结与个人体会

“为什么 Chromium 要封装一套自己的基础库?”
—— 因为它不是普通项目,它需要在 几十年生命周期 + 数十个平台 + 上千万行代码 + 数千开发者并行协作 的体系中保持一致性和可维护性。

base 提供的不是简单的工具集合,而是一组被严格校验过的“架构支点”。

核心认识
✅ 它支撑了浏览器的线程模型、任务调度、安全调用和设备无关性
✅ 它保证了跨平台行为完全一致
✅ 它将复杂体系拆成了可维护、可测试的模块单位
✅ 它提升了性能,并避免了 STL 在大型工程场景的不可控因素
✅ 它是进入 Chromium 内核体系的最佳入口

如果你想真正理解浏览器内核架构,从 base 开始绝对是一个正确的打开方式。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ปรัชญา แค้วคำมูล

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值