核心:Chrome 浏览器采用多进程架构,渲染进程通过主线程、合成器线程、光栅化线程池协同工作,将HTML/CSS/JS转化为屏幕像素。本文深入剖析从URL输入到像素绘制的完整过程。

一、浏览器多进程架构

现代浏览器不是单一程序,而是由多个进程协作组成的复杂系统。Chrome 采用多进程架构,将不同功能隔离到独立进程,提升稳定性和安全性。

Chrome 多进程架构全景图
graph TB subgraph Browser["浏览器主进程 Browser Process"] B1[UI界面控制] B2[网络请求调度] B3[文件访问] B4[进程管理] end subgraph Renderer["渲染进程 Renderer Process"] R1[主线程 Main Thread] R2[合成器线程 Compositor] R3[光栅化线程池 Raster] end subgraph GPU["GPU进程 GPU Process"] G1[3D绘制] G2[硬件加速] end subgraph Network["网络进程 Network Process"] N1[HTTP请求] N2[资源下载] end subgraph Plugin["插件进程 Plugin Process"] P1[PDF] end Browser -->|IPC通信| Renderer Browser -->|IPC通信| GPU Browser -->|IPC通信| Network Browser -->|IPC通信| Plugin Renderer -->|发送绘制指令| GPU Network -->|返回资源| Renderer style Browser fill:#409EFF,stroke:#409EFF,color:#FFFFFF style Renderer fill:#67C23A,stroke:#67C23A,color:#FFFFFF style GPU fill:#E6A23C,stroke:#E6A23C,color:#FFFFFF style Network fill:#F56C6C,stroke:#F56C6C,color:#FFFFFF style Plugin fill:#909399,stroke:#909399,color:#FFFFFF

1.1 核心进程职责

进程类型 主要职责 数量 隔离意义
浏览器主进程
Browser Process
控制地址栏、书签、前进后退,管理其他进程 1个 核心控制中心
渲染进程
Renderer Process
HTML/CSS/JS解析、排版、绘制 每个标签页1个 标签页崩溃不影响其他
GPU进程
GPU Process
处理来自所有进程的GPU任务 1个 统一管理硬件资源
网络进程
Network Process
处理网络请求、资源加载 1个 集中管理网络资源
插件进程
Plugin Process
运行浏览器插件 按需创建 插件崩溃不影响浏览器

类比理解:浏览器像一个大公司,主进程是CEO,渲染进程是各部门项目组(互不干扰),GPU进程是设计部(统一处理视觉工作),网络进程是采购部(统一对外联络),插件进程是外包团队(失败不影响主业务)。

二、从 URL 到页面显示的完整旅程

URL 输入到页面显示全流程
sequenceDiagram participant U as 用户 participant B as 浏览器主进程 participant N as 网络进程 participant R as 渲染进程 participant G as GPU进程 U->>B: 输入 URL 并回车 B->>B: 检查缓存 B->>N: 发起网络请求 Note over N: DNS解析 → TCP连接 → HTTP请求 N->>N: 接收响应头 N->>B: 通知准备渲染 B->>R: 创建/复用渲染进程 N->>R: 提交文档数据(HTML) Note over R: 开始渲染流水线 R->>R: 解析 HTML → DOM树 R->>R: 解析 CSS → CSSOM树 R->>R: 合成 Render Tree R->>R: 布局计算(Layout) R->>R: 分层(Layer) R->>R: 绘制(Paint) R->>R: 分块(Tile) R->>R: 光栅化(Raster) R->>G: 发送绘制指令 G->>G: GPU绘制合成 G->>U: 屏幕显示页面 Note over U: 页面完整呈现
1
导航阶段
主进程
用户输入URL → 主进程判断是搜索关键词还是网址 → 更新UI(地址栏显示加载动画) → 通知网络进程发起请求
2
网络请求
网络进程
DNS解析域名 → 建立TCP连接(三次握手) → TLS握手(HTTPS) → 发送HTTP请求 → 接收响应
3
准备渲染
主进程
检查响应头(Content-Type: text/html) → 检查是否需要新建渲染进程 → 告知渲染进程准备接收数据
4
提交文档
渲染进程
渲染进程和网络进程建立数据管道 → 网络进程持续传输HTML数据 → 渲染进程开始解析并渲染
5
渲染流水线
渲染进程
执行完整的渲染流程(详见下文),最终生成位图并提交给GPU进程
6
显示页面
GPU进程
GPU进程将多个图层合成到屏幕缓冲区 → 显示器从缓冲区读取数据 → 用户看到完整页面

三、渲染进程深度剖析

渲染进程是浏览器渲染的核心,负责将HTML/CSS/JS转化为屏幕像素。它内部由多个线程协作完成复杂任务。

渲染进程内部线程架构
graph LR subgraph RendererProcess["渲染进程 Renderer Process"] subgraph MainThread["主线程 Main Thread"] M1[解析HTML/CSS] M2[执行JavaScript] M3[样式计算] M4[布局计算] M5[绘制记录] end subgraph CompositorThread["合成器线程 Compositor Thread"] C1[接收输入事件] C2[管理图层] C3[分块任务调度] C4[提交绘制指令] end subgraph RasterThreads["光栅化线程池 Raster Threads"] RT1[线程1: 光栅化Tile] RT2[线程2: 光栅化Tile] RT3[线程3: 光栅化Tile] RT4[线程N: 光栅化Tile] end end M5 -->|发送绘制记录| C2 C3 -->|分配任务| RasterThreads RasterThreads -->|返回位图| C4 C4 -->|Draw Quads| GPU[GPU进程] style MainThread fill:#409EFF,stroke:#409EFF,color:#FFFFFF style CompositorThread fill:#67C23A,stroke:#67C23A,color:#FFFFFF style RasterThreads fill:#E6A23C,stroke:#E6A23C,color:#FFFFFF

3.1 主线程(Main Thread)

主线程是渲染进程的指挥家,负责执行大部分关键任务:

  • 解析HTML → 构建DOM树(Document Object Model)
  • 解析CSS → 构建CSSOM树(CSS Object Model)
  • 执行JavaScript → 可能修改DOM/CSSOM,阻塞渲染
  • 样式计算 → 计算每个DOM节点的最终样式
  • 布局计算 → 计算元素的几何位置和尺寸
  • 分层 → 为某些元素创建独立的渲染层
  • 绘制 → 生成绘制指令列表(Paint Records)

性能瓶颈:主线程是单线程,长时间运行的JavaScript会阻塞渲染,导致页面卡顿。这就是为什么复杂计算要放到Web Worker中。

3.2 合成器线程(Compositor Thread)

合成器线程是渲染进程的优化核心,专门负责图层管理和合成:

  • 图层树管理 → 接收主线程的图层树(Layer Tree)
  • 视口分块 → 将图层分割为256×256或512×512的Tile
  • 优先级调度 → 优先光栅化视口内的Tile
  • 输入事件响应 → 独立处理滚动、缩放,不依赖主线程
  • 合成帧提交 → 将所有图层合成后提交给GPU

性能优势:合成器线程独立于主线程运行,即使主线程被JavaScript阻塞,滚动动画依然流畅(前提是使用了transform/opacity等合成属性)。

3.3 光栅化线程池(Raster Threads)

光栅化线程池是渲染进程的劳动力,专门将矢量图形转化为位图像素:

  • 并行光栅化 → 多个线程同时处理不同Tile
  • GPU加速 → 可选择GPU光栅化(更快)
  • 位图缓存 → 光栅化结果缓存到GPU显存

关键概念:光栅化(Rasterization)

光栅化是将矢量图形(HTML/CSS描述的元素)转换为像素点的过程。比如CSS写的圆角矩形,光栅化后变成具体的RGBA像素值,可以直接显示在屏幕上。

四、渲染流水线五大阶段

从HTML到像素的转化过程,称为渲染流水线(Rendering Pipeline),包含5个核心阶段。

渲染流水线完整流程
graph TD Start([HTML/CSS/JS]) --> Parse subgraph Stage1["阶段1: 解析 Parse"] Parse[解析HTML] --> DOM[构建DOM树] ParseCSS[解析CSS] --> CSSOM[构建CSSOM树] end subgraph Stage2["阶段2: 样式 Style"] DOM --> Attach[Attachment] CSSOM --> Attach Attach --> RenderTree[Render Tree 渲染树] end subgraph Stage3["阶段3: 布局 Layout"] RenderTree --> LayoutCalc[计算几何位置] LayoutCalc --> LayoutTree[Layout Tree
位置+尺寸] end subgraph Stage4["阶段4: 分层绘制 Paint"] LayoutTree --> Layer[创建图层 Layer Tree] Layer --> PaintRecord[生成绘制指令
Paint Records] end subgraph Stage5["阶段5: 合成 Composite"] PaintRecord --> Tile[分块 Tiling] Tile --> Raster[光栅化 Rasterization] Raster --> DrawQuads[生成绘制四边形] DrawQuads --> GPU[提交GPU进程] end GPU --> Display([屏幕显示]) style Stage1 fill:#ECF5FF,stroke:#409EFF style Stage2 fill:#F0F9FF,stroke:#67C23A style Stage3 fill:#FDF6EC,stroke:#E6A23C style Stage4 fill:#FEF0F0,stroke:#F56C6C style Stage5 fill:#F4F4F5,stroke:#909399

阶段 1:解析(Parse)

HTML解析 → DOM树

浏览器逐字节读取HTML,通过词法分析和语法分析构建DOM树。

  • 遇到 <script> 标签会阻塞解析(除非有 async/defer)
  • 遇到 <link> 标签加载CSS不阻塞HTML解析,但阻塞渲染
  • 遇到 <img> 标签会异步加载图片
CSS解析 → CSSOM树

并行解析CSS,构建CSSOM树。CSS选择器匹配规则从右向左(提高效率)。

阶段 2:样式计算(Style)

合并生成渲染树(Render Tree)

将DOM树和CSSOM树合并,计算每个可见节点的最终样式。

  • 排除不可见节点(display: none<head><script>
  • 处理CSS继承、层叠、优先级
  • 计算出每个元素的Computed Style(最终生效样式)

阶段 3:布局(Layout)

计算几何信息
性能敏感

计算每个元素在视口中的精确位置和尺寸,生成布局树(Layout Tree)。

  • 盒模型计算(content + padding + border + margin)
  • 流式布局(正常流、浮动、定位)
  • Flex/Grid布局算法
  • 文字换行、行高计算

触发重排(Reflow)的操作:修改元素尺寸、增删DOM、改变窗口大小等,代价昂贵。

阶段 4:分层与绘制(Paint)

创建图层(Layer)

浏览器为某些元素创建独立的渲染层(Render Layer)合成层(Compositing Layer)

提升为合成层的条件:

  • 3D变换:transform: translateZ(0)will-change: transform
  • 视频、Canvas、iframe元素
  • position: fixed
  • CSS滤镜:filterbackdrop-filter
  • 透明度动画:opacity 小于1且有动画
生成绘制记录(Paint Records)

遍历渲染树,生成绘制指令列表(类似Canvas API调用):

// 绘制记录示例(伪代码)
drawRect(0, 0, 100, 100, color: '#409EFF')
drawText('Hello', 10, 50, font: '16px Arial')
drawImage(img, 0, 0, 200, 200)

触发重绘(Repaint)的操作:修改颜色、背景、阴影等视觉样式。比重排代价小,但也应避免频繁触发。

阶段 5:分块、光栅化与合成(Composite)

这是浏览器渲染的精华部分,也是性能优化的关键。

分层、分块、光栅化、合成详细流程
graph TB LayerTree[主线程: Layer Tree] --> Compositor subgraph CompositorWork["合成器线程工作"] Compositor[接收图层树] --> Tiling[分块 Tiling] Tiling --> TileGrid[Tile网格
256×256像素] TileGrid --> Priority{优先级判断} Priority -->|视口内| HighPriority[高优先级队列] Priority -->|视口外| LowPriority[低优先级队列] end subgraph RasterWork["光栅化线程池工作"] HighPriority --> Raster1[线程1: GPU光栅化] HighPriority --> Raster2[线程2: GPU光栅化] LowPriority --> Raster3[线程3: GPU光栅化] Raster1 --> Bitmap1[位图1] Raster2 --> Bitmap2[位图2] Raster3 --> Bitmap3[位图3] end Bitmap1 --> GPUMemory[GPU显存缓存] Bitmap2 --> GPUMemory Bitmap3 --> GPUMemory GPUMemory --> DrawQuads[生成绘制四边形
Draw Quads] DrawQuads --> GPUProcess[提交GPU进程] GPUProcess --> Display[屏幕显示] style Tiling fill:#409EFF,stroke:#409EFF,color:#FFFFFF style Raster1 fill:#67C23A,stroke:#67C23A,color:#FFFFFF style Raster2 fill:#67C23A,stroke:#67C23A,color:#FFFFFF style Raster3 fill:#67C23A,stroke:#67C23A,color:#FFFFFF style DrawQuads fill:#E6A23C,stroke:#E6A23C,color:#FFFFFF
1
分块(Tiling)
合成器线程
将每个图层分割为固定大小的瓦片(Tile),通常是256×256或512×512像素。类似地图应用的瓦片加载策略,只渲染可见区域,节省资源。
2
优先级排序
合成器线程
优先光栅化视口内的Tile(用户能看到的部分),视口外的Tile延迟处理。滚动时动态调整优先级。
3
光栅化(Rasterization)
光栅化线程池
将绘制指令转化为实际像素位图。浏览器支持两种模式:
• 软件光栅化:CPU执行,慢但兼容性好
• GPU光栅化:GPU执行,快速且是默认模式
4
生成绘制四边形(Draw Quads)
合成器线程
为每个Tile生成绘制四边形指令,包含位图在GPU显存中的位置、要绘制的屏幕区域、变换矩阵等信息。
5
提交合成帧(Compositor Frame)
GPU进程
合成器线程将所有Draw Quads提交给GPU进程,GPU进程执行最终合成,将多个图层合并到屏幕缓冲区。

核心优化原理

为什么 transform 和 opacity 动画性能好?
因为它们只影响合成阶段,不需要重新布局和绘制。合成器线程可以独立完成动画,即使主线程被JavaScript阻塞,动画依然流畅60fps。

为什么修改 width/height 会卡顿?
因为会触发重排,需要重新执行布局、绘制、分块、光栅化整个流水线,代价极高。

五、帧渲染与性能优化

流畅的动画需要60fps(每秒60帧),即每帧只有16.6ms。浏览器需要在这极短时间内完成所有渲染工作。

单帧渲染时间线(16.6ms 预算)
gantt title 理想帧渲染时间分配(总预算 16.6ms) dateFormat X axisFormat %L ms section 主线程 执行JavaScript :0, 3 样式计算 :3, 5 布局计算 :5, 8 绘制记录 :8, 10 section 合成器线程 分块调度 :10, 11 提交合成帧 :14, 15 section 光栅化线程池 GPU光栅化 :11, 14 section GPU进程 合成显示 :15, 16

5.1 性能优化黄金法则

优化方向 具体策略 影响阶段 性能提升
避免强制同步布局 读取布局信息后不要立即修改样式 布局 5星
使用合成属性 动画优先使用 transform/opacity 合成 5星
提升合成层 will-change: transform 合成 4星
减少绘制区域 避免大面积重绘 绘制 3星
降低选择器复杂度 避免深层嵌套选择器 样式 2星
代码分割 拆分长任务,使用 requestIdleCallback JavaScript 4星

5.2 重排、重绘、合成对比

操作类型 触发属性示例 执行阶段 性能代价
重排(Reflow) width、height、margin、padding、display、position 布局 → 绘制 → 合成 极高
重绘(Repaint) color、background、box-shadow、border-radius 绘制 → 合成 中等
仅合成(Composite) transform、opacity、filter 合成 极低

5.3 实战案例:滚动性能优化

低性能写法(会阻塞主线程)

// 滚动时频繁修改DOM
window.addEventListener('scroll', () => {
  const scrollTop = document.documentElement.scrollTop;
  document.querySelector('.header').style.height = (100 - scrollTop / 10) + 'px'; // 触发重排
});

高性能写法(合成器线程处理)

// 使用 transform 替代修改尺寸
window.addEventListener('scroll', () => {
  const scrollTop = document.documentElement.scrollTop;
  const scale = Math.max(0.5, 1 - scrollTop / 1000);
  document.querySelector('.header').style.transform = `scaleY(${scale})`; // 仅触发合成
}, { passive: true }); // passive 告知浏览器不会调用 preventDefault

六、关键技术总结

技术名词 英文 作用 所属线程
DOM树 Document Object Model HTML结构的内存表示 主线程
CSSOM树 CSS Object Model CSS规则的内存表示 主线程
渲染树 Render Tree 可见元素+样式的树形结构 主线程
布局树 Layout Tree 包含几何位置信息的树 主线程
图层树 Layer Tree 分层后的渲染层集合 主线程 → 合成器线程
分块 Tiling 将图层切分为小瓦片 合成器线程
光栅化 Rasterization 矢量图转位图像素 光栅化线程池
绘制四边形 Draw Quads GPU绘制指令 合成器线程
合成帧 Compositor Frame 最终提交给GPU的帧数据 合成器线程

核心设计思想:Chrome通过多进程隔离提升稳定性,通过多线程并行提升性能,通过分层合成机制实现流畅动画。理解渲染流水线,才能写出真正高性能的Web应用。记住:主线程负责思考(解析、计算),合成器线程负责执行(合成、动画),光栅化线程池负责干活(绘制像素)