前端性能之浏览器工作原理

509 阅读7分钟

进程与线程

  • 进程 (Process)
    • 进程是操作系统分配资源(如内存、CPU)的基本单位,不同进程之间相互隔离,一个进程崩溃不会直接影响其他进程。
    • 例子:Chrome 浏览器中,每个标签页、插件、网络请求等都可能运行在独立的进程中。
  • 线程 (Thread)
    • 线程是进程内的执行单元,共享进程的内存空间。多线程可以提高并发性能,但线程间缺乏隔离,一个线程崩溃可能导致整个进程崩溃。

浏览器多进程架构

为什么需要多进程架构?

在早期的单进程浏览器时代(如 IE 6),浏览器所有功能(页面渲染、网络请求、JavaScript 执行、插件运行等)都运行在同一个进程中。这种架构虽然简单,但存在诸多致命问题:

1. 稳定性差:一崩全崩
  • 问题 :单进程中,页面渲染、插件或 JavaScript 的崩溃会导致整个浏览器崩溃。
  • 示例 :一个 Flash 插件崩溃可能让用户丢失所有已打开的标签页。
  • 用户痛点 :“我只是想关掉一个卡住的页面,结果整个浏览器都没了!”
2. 安全性低:漏洞扩散无阻
  • 问题 :所有代码共享同一进程内存,恶意脚本或插件可轻易攻击浏览器核心功能(如窃取 Cookie 或文件)。
  • 案例 :早期的浏览器漏洞常通过 JavaScript 直接读写用户磁盘。
3. 性能瓶颈:资源争抢严重
  • 问题 :网络请求、页面渲染、UI 响应等任务在同一进程中竞争 CPU 和内存资源。
  • 现象 :打开多个标签页时,浏览器卡顿明显,甚至出现“无响应”状态。
4. 扩展性差:难以利用多核 CPU
  • 问题 :单进程只能使用单线程或有限线程,无法充分发挥多核硬件的优势。
  • 后果 :随着网页复杂度提升(如 WebGL、视频解码),单进程架构性能捉襟见肘。

2008 年,Chrome 首次引入多进程架构,将浏览器拆分为多个独立进程,实现了隔离性并行化安全性 的飞跃。这种设计迅速成为现代浏览器的标准(如 Firefox 的 Project Fission、Edge 的进程模型)。

核心进程

进程名称英文功能描述
浏览器主进程Browser Process负责管理浏览器窗口、地址栏、书签、下载等全局功能,协调其他进程的创建和销毁
渲染进程Renderer Process每个标签页或 iframe 对应一个进程(同源策略下可能共享),负责页面 HTML/CSS/JS 解析、渲染和事件处理。
GPU 进程GPU Process独立处理图形渲染任务(如 CSS 动画、WebGL),通过硬件加速提升性能,降低主进程负载。
网络服务进程Network Service Process统一管理所有网络请求(HTTP/WebSocket)、DNS 解析、缓存和 Cookie(自 Chrome 67 起独立为单独进程)。
扩展进程Extension Process每个浏览器扩展运行在独立进程中,防止恶意插件影响浏览器主进程或其他标签页。
实用进程Utility Process处理临时任务,如音视频解码(Utility: Audio Service)、文件解析(Utility: Data Decoder)等,完成后自动销毁

多进程架构的优势

1. 稳定性:进程隔离,崩溃可控
  • 原理 :每个标签页运行在独立渲染进程中,崩溃仅影响当前标签。
  • 用户价值
    • 卡住的网页可以直接关闭,无需重启整个浏览器。
    • 通过 chrome://crash 可手动测试单个标签页崩溃的恢复能力。
  • 技术实现
    • 浏览器主进程监控子进程状态,自动重启崩溃的渲染进程。
2. 安全性:沙箱隔离,漏洞难逃
  • 原理 :关键进程(如渲染进程、网络进程)运行在沙箱(Sandbox)中,权限被严格限制。
  • 示例
    • 渲染进程无法直接读写磁盘文件(需通过浏览器主进程代理)。
    • 恶意代码无法通过渲染进程攻击操作系统。
  • 技术实现
    • 操作系统级隔离(如 Windows 的 Job 对象、Linux 的命名空间)。
3. 性能:多核并行,各司其职
  • 原理 :不同进程可绑定到不同 CPU 核心,实现真正的并行计算。
  • 场景优化
    • GPU 进程 :专用于图形渲染,支持 3D 动画和 WebGL 高性能计算。
    • 网络进程 :统一管理 TCP 连接池、DNS 缓存,减少重复请求开销。
  • 数据佐证 :多进程架构下,Chrome 的页面加载速度和响应延迟显著优于早期单进程浏览器。
4. 资源管理:按需分配,动态调度
  • 原理 :浏览器主进程统一协调资源分配,避免浪费。
  • 策略举例
    • 后台标签页冻结 :减少非活动标签页的 CPU 和内存占用。
    • 进程复用 :同源网站共享渲染进程(可通过 chrome://process-internals 查看)。
5. 扩展性:功能模块化,迭代更灵活
  • 原理 :每个功能模块(如网络、存储、扩展)可独立升级或替换。
  • 案例
    • Chrome 的 Network Service 进程化后,网络层更新无需重启整个浏览器。
    • Site Isolation 功能通过强化进程隔离,防御 Spectre 等硬件级漏洞。

浏览器导航与渲染

1. 输入阶段(浏览器主进程)
  • 输入预处理
    • 地址栏输入时,浏览器主进程的 UI线程 会先进行安全检查(如防止 XSS 攻击字符过滤)
    • HSTS 检查 :强制 HTTPS(若域名在 HSTS 列表中,直接跳 HTTPS)
    • 预连接优化 :Chrome 会对高频域名提前建立 TCP 连接(如搜索框输入时)
2. 网络请求阶段(网络进程)

  • DNS 解析优化
    • 浏览器缓存 → 本地 Hosts → DNS 预取( <link rel="dns-prefetch"> ) → 递归查询
    • DNS over HTTPS (DoH) :现代浏览器默认开启加密 DNS
  • TCP 连接复用
    • 检查是否有可用 Keep-Alive 连接(减少 3 次握手开销)
    • 若启用 QUIC(HTTP/3),直接建立 UDP 连接
  • 响应处理
    • 内容嗅探(MIME Sniffing) :若 Content-Type 缺失/错误,通过文件内容推断类型
    • 安全校验
      • 跨域响应检查(CORS)
      • CSP(Content Security Policy)验证
      • 恶意内容扫描(如 Chrome 的 Safe Browsing)
3. 准备渲染进程(浏览器主进程)

  • 进程分配策略
    • Site Isolation :同源策略下同一站点(eTLD+1)复用进程
    • 超过进程数限制时,LRU 策略回收旧进程
  • 沙箱初始化
    • 渲染进程启动后,立即启用沙箱(限制文件系统访问、系统调用等)
4. 渲染阶段(渲染进程主线程)
  • 解析(Parse)
    • 预解析扫描器(Preload Scanner) :提前发现 CSS/JS/图片等资源并触发加载
    • DOM 构建 :遇到 <script> 时,根据 async/defer 决定是否阻塞解析
  • 样式计算(Style)
    • 层叠上下文优化 :浏览器会缓存部分计算结果(如复用相同类名的样式)
  • 布局(Layout)
    • 增量布局 :仅重新计算受影响元素(如窗口 resize 时)
    • CSS Containment :通过 contain: strict 属性限制布局范围以优化性能
  • 分层(Layer)
    • 根据 will-changetransform 等属性决定是否提升为独立合成层
5. 合成与光栅化(渲染进程合成线程 + GPU 进程)
  • 分块(Tiling)
    • 视口附近的图块优先级更高(优先光栅化)
  • 光栅化(Raster)
    • GPU 加速 :使用 Skia(Chrome)或 Core Graphics(Safari)渲染 2D 图形
    • 部分光栅化 :只渲染可见区域,滚动时动态加载
  • Draw Quads
    • 生成绘制指令(如纹理坐标),提交给 GPU 进程的 Command Buffer
6. 最终显示(浏览器主进程 + GPU 进程)
  • 帧提交
    • GPU 进程通过 OpenGL/Vulkan 接口提交到显示合成器(Display Compositor)
    • 垂直同步(VSync)信号触发屏幕刷新
  • 界面更新
    • 浏览器主进程停止地址栏旋转图标,更新历史记录和页面标题