Skip to content

各进程内的线程

基于 Chromium 现代架构 · 核于 2026-07

速查

  • browser 进程三大员:UI 线程(画地址栏/按钮、判定输入、路由用户操作)、network 线程(网络栈——现代已移入独立 Network Service 进程)、storage 线程(文件与存储访问)
  • renderer 主线程(main thread):解析 HTML→DOM、样式计算、布局树、绘制记录、执行你的 JS、事件命中与派发——一人分饰全部关键角色
  • compositor 线程:把页面分层、生成合成帧(compositor frame);不经主线程也能处理滚动/动画
  • raster 线程 ×N:把 compositor 切好的**图块(tile)**光栅化成位图,存入 GPU 内存
  • worker 线程:Web Worker / Service Worker 的 JS 在这里跑,与主线程只通消息
  • Viz 进程(原 GPU 进程,全浏览器仅一个——「通常只有一块 GPU」):display compositor 线程聚合各 renderer + browser 的合成帧为单帧;GPU main 线程光栅化并真正画上屏幕
  • display compositor 单独成线程的理由:必须时刻可响应,不能被 GPU 慢操作阻塞
  • 帧的旅程:renderer 各自产出 compositor frame --IPC→ Viz 聚合 → GPU 绘制上屏
  • 演进注记:inside-browser 系列(2018)描述的「browser 进程 network 线程」「GPU 进程」,在现代 Chromium 中分别演进为 Network ServiceViz
  • 对前端:JS、布局、样式全挤在主线程 → 长任务卡一切;transform/opacity 动画可走 compositor 线程绕开主线程

一、browser 进程:UI、网络、存储三条线

多进程解决「谁和谁隔离」,进程内部还要靠线程分工。先看总调度 browser 进程,导航一章(一次导航的全流程)的主角就是这几条线:

线程职责
UI 线程绘制浏览器自身界面(地址栏、按钮、tab 条);判定地址栏输入;编排导航
network 线程跑网络栈,从互联网收发数据(DNS、连接、响应)
storage 线程控制文件访问与各类存储

两点补充:

  • network 线程的现代归宿:这是 2018 年 inside-browser 系列的描述;随服务化推进,网络栈已移入独立的 Network Service 进程(资源受限设备上可回退为进程内线程)。本叶叙述导航时仍沿用「network 线程/网络侧」的说法,读者对号入座即可。
  • RenderingNG 视角:browser 进程还有自己的「渲染与合成」职责——浏览器 UI 本身也要布局和绘制,并把输入事件路由给正确的 renderer;因无性能隔离需求,这些由单一线程(配少量 helper 线程做图像解码等)承担。

二、renderer 进程:主线程和它的帮手们

renderer 是 tab 内的整个世界,每个 tab(站点隔离下每个 site)一个。内部线程分工是前端性能话题的核心地图:

text
renderer 进程
├─ main thread(主线程)×1
│    解析 HTML → DOM · 样式计算 · 布局树 · 绘制记录
│    执行 JS · 事件命中测试与派发 · 文档生命周期
├─ compositor thread(合成器线程)×1
│    分层(layerization)· 滚动/部分动画 · 产出 compositor frame
├─ raster threads(光栅化线程)×N
│    把 tile 变成位图,写入 GPU 内存
└─ worker threads ×N
     Web Worker / Service Worker 的 JS · 媒体/音频等辅助线程

2.1 主线程:唯一跑你 JS 的地方

主线程包揽了渲染管线的关键环节:把 HTML 解析成 DOM、算每个节点的样式、构建布局树(几何与位置)、生成绘制记录(先画什么后画什么)、构建分层信息并提交给 compositor 线程——外加执行你的所有 JS 和派发输入事件。各环节细节属浏览器渲染原理叶,这里只需看清一件事:这么多活挤在一条线程上,一个长任务就能让解析、渲染、交互全部排队。Web Worker / Service Worker 之所以存在,就是把可挪的 JS 挪去 worker 线程。

2.2 compositor 线程:没有主线程也要能滚

合成(compositing)是把页面拆成多个图层(layer)、各自光栅化、再拼成一帧的技术,由独立的 compositor 线程主持。它的独立价值在于:输入滚动、图层级动画可以完全不等主线程——主线程哪怕正被 JS 卡住,compositor 线程照样让页面滚起来。它还负责计算分层、协调图像解码与光栅化任务。

2.3 raster 线程:把图层切块变位图

图层可能很大(比如整页长图层),compositor 线程把它切成图块(tile)分发给多条 raster 线程;raster 线程把 tile 光栅化成位图存进 GPU 内存。compositor 线程会优先光栅化视口附近的 tile。随后 compositor 把「哪些 tile、放哪、怎么拼」封装成 draw quad,聚合为一张 compositor frame(合成帧),经 IPC 提交出去。

三、Viz 进程:全浏览器只有一个的「上屏部门」

原「GPU 进程」在现代 Chromium 重构为 Viz(取自 Visuals)。整个浏览器只有一个 Viz 进程——理由朴素:「通常只有一块 GPU」。它接收所有 renderer 进程和 browser 进程各自提交的 compositor frame,聚合后画上屏幕。内部两条关键线程:

线程职责
display compositor 线程把各进程的合成帧聚合、优化成一张全局帧
GPU main 线程光栅化显示列表与视频帧为 GPU 纹理 tile;把合成帧真正绘制到屏幕

为什么 display compositor 不和 GPU main 挤一条线程?官方解释:display compositor 必须时刻保持响应,不能被 GPU 上的慢操作阻塞——聚合调度与真正画图解耦,掉帧风险被隔离在 GPU main 一侧。

一帧画面的完整旅程(站点隔离下一个页面可能由多个 renderer 拼成,聚合正是 Viz 的价值):

text
renderer A(主文档)─ compositor frame ─┐
renderer B(跨站 iframe)─ compositor frame ─┼─► Viz:display compositor 聚合成单帧
browser 进程(浏览器 UI)─ compositor frame ─┘        └─► GPU main 绘制上屏

四、演进注记:从 2018 年的图景到现在

inside-browser 系列(2018)与 RenderingNG 文档(2021+)之间,有两处名词更替需要对齐,读旧文章时别错乱:

2018 年说法现代 Chromium
browser 进程内的 network 线程独立 Network Service 进程(服务化,弱设备可合并)
GPU 进程Viz 进程(display compositor + GPU main)
compositor frame 先提交给 browser 进程再转 GPUrenderer 直接把 compositor frame 提交给 Viz 聚合

架构在演进,但分工哲学未变:每条线程只守一类职责,跨线程/跨进程只传消息

五、在 DevTools 里认出这些线程

Performance 面板录一段 trace,泳道与本页线程一一对应——这是把抽象架构落到日常调试的桥:

Performance 泳道对应线程常看什么
Mainrenderer 主线程长任务(红角标)、Parse HTML、Recalculate Style、Layout、Paint
Compositorrenderer compositor 线程滚动/合成是否独立推进;等主线程的空洞
Raster(Rasterizer ×N)raster 线程光栅化耗时、tile 任务分布
Thread pool / Workerworker 线程你的 Worker JS 是否真把活挪出去了
GPUViz 侧工作上屏是否成为瓶颈

一个常用判读:页面滚动流畅但点击无响应——Compositor 泳道在动、Main 泳道被长任务塞满,正是「合成器线程独立于主线程」的教科书现场。

六、对前端工程师的实际影响

  • 长任务卡一切:样式、布局、事件派发与你的 JS 同挤主线程——拆长任务、上 Worker 是架构层面的对症下药。
  • 合成器动画丝滑的原理:只改 transform/opacity 的动画可在 compositor 线程独立推进,主线程卡死也不掉帧;改布局属性的动画则必须回主线程走全管线(详见浏览器渲染原理)。
  • 滚动为什么不容易卡:滚动默认由 compositor 线程处理;但注册非 passive 的 touchmove/wheel 监听会迫使合成器等主线程确认,滚动性能应声而降。
  • iframe 多 ≠ 只费内存:每个跨站 iframe 的帧要在 Viz 聚合,进程/线程编排成本也随之增加。

小结

browser 进程用 UI、network、storage 三条线程编排全局;renderer 进程里主线程一人扛下解析、样式、布局、JS 与事件,compositor 线程负责分层与合成帧、raster 线程切块光栅化、worker 线程收留后台 JS;全浏览器唯一的 Viz 进程用 display compositor 线程聚合各方合成帧、GPU main 线程绘制上屏。名词随架构演进(network 线程 → Network Service,GPU 进程 → Viz),但「单一职责 + 消息传递」的分工哲学一以贯之。看懂了线程分工,就能解释为什么长任务卡交互、合成器动画不掉帧。下一页把进程边界再切细一刀:站点隔离