一、基本概念区分
1. 进程(Process)
- 定义:操作系统资源分配的基本单位,拥有独立的地址空间
- 特点 :
- 独立内存空间
- 进程间通信(IPC)成本高
- 创建和销毁开销大
- 崩溃不会影响其他进程
2. 线程(Thread)
- 定义:CPU调度的基本单位,共享进程资源
- 特点 :
- 共享进程内存空间
- 线程间通信成本低
- 创建和销毁开销小
- 一个线程崩溃可能导致整个进程崩溃
3. 浏览器中的对应关系
复制代码
浏览器进程
├── GPU进程
├── 渲染进程(多个标签页)
│ ├── 主线程(UI、JS)
│ ├── 工作线程(Web Worker)
│ ├── 合成线程
│ └── 光栅线程
├── 网络进程
└── 插件进程
二、浏览器多进程架构
1. 主要进程类型
进程类型 |
职责 |
数量 |
浏览器主进程 |
界面显示、用户交互、子进程管理 |
通常1个 |
渲染进程 |
页面渲染、脚本执行 |
每个标签页1个(通常) |
GPU进程 |
3D绘制、CSS动画加速 |
通常1个 |
网络进程 |
资源加载、网络请求 |
通常1个 |
插件进程 |
运行浏览器插件 |
每种插件1个 |
2. 进程隔离的优势
- 安全性:沙箱机制防止恶意代码影响系统
- 稳定性:单个页面崩溃不会影响整个浏览器
- 性能:多核CPU并行处理
- 内存回收:关闭页面后完整释放资源
3. Chrome的多进程模型演进
- 早期:单进程(所有标签共享)
- 中期:多标签多进程
- 现在:面向站点隔离(Site Isolation)的进程模型
三、渲染进程中的多线程
1. 主线程(UI线程)
- 职责 :
- 解析HTML/CSS(DOM/CSSOM构建)
- 执行JavaScript
- 布局(Layout)
- 绘制(Paint)
- 特点 :
- 与用户交互直接相关
- 长时间任务会导致页面卡顿
- 采用事件循环(Event Loop)机制
2. 工作线程(Web Worker)
javascript
复制代码
// 主线程
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.onmessage = e => console.log(e.data);
// worker.js
self.onmessage = e => {
const result = processData(e.data);
self.postMessage(result);
};
- 特点 :
- 独立全局上下文(无DOM访问权限)
- 通过postMessage通信
- 适合CPU密集型任务
3. 其他重要线程
- 合成线程(Compositor Thread) :
- 光栅线程(Raster Thread) :
- Service Worker线程 :
四、事件循环(Event Loop)机制
1. 任务队列类型
- 宏任务(Macro Task) :
- script整体代码
- setTimeout/setInterval
- I/O操作
- UI渲染
- postMessage
- 微任务(Micro Task) :
- Promise.then/catch/finally
- MutationObserver
- process.nextTick(Node.js)
2. 执行顺序
- 执行一个宏任务(从事件队列中获取)
- 执行所有微任务(直到微任务队列清空)
- 必要时渲染UI
- 开始下一个宏任务
javascript
复制代码
console.log('script start'); // 宏任务
setTimeout(() => {
console.log('setTimeout'); // 宏任务
}, 0);
Promise.resolve().then(() => {
console.log('promise1'); // 微任务
}).then(() => {
console.log('promise2'); // 微任务
});
console.log('script end'); // 宏任务
/*
输出顺序:
script start
script end
promise1
promise2
setTimeout
*/
五、Web Workers 深度解析
1. 专用Worker(Dedicated Worker)
- 一对一通信(主线程 ↔ Worker线程)
- 生命周期与创建页面绑定
- 典型应用:
2. 共享Worker(Shared Worker)
javascript
复制代码
// 多个页面共享同一个Worker
const worker = new SharedWorker('shared.js');
worker.port.start();
worker.port.postMessage(data);
- 多页面共享
- 通过port通信
- 需显式调用port.start()
3. Worker使用限制
- 无法访问 :
- DOM/BOM API
- document/window对象
- 主线程变量
- 可用功能 :
- WebSockets
- IndexedDB
- 计算密集型API(如WebAssembly)
4. 性能优化技巧
- 批量传输数据(避免频繁postMessage)
- 使用Transferable Objects(零拷贝)
javascript
复制代码
// 转移ArrayBuffer所有权(不复制数据)
worker.postMessage(bigArrayBuffer, [bigArrayBuffer]);
六、Service Worker 进阶
1. 生命周期
- 注册 :
navigator.serviceWorker.register()
- 安装:install事件(缓存资源)
- 激活:activate事件(清理旧缓存)
- 运行:处理fetch等事件
2. 典型缓存策略
javascript
复制代码
// 缓存优先策略
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(cached => cached || fetch(event.request))
);
});
// 网络优先策略
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request)
.catch(() => caches.match(event.request))
);
});
3. 高级功能
- 后台同步:处理离线时的数据同步
- 推送通知:显示系统通知
- 地理围栏:基于位置触发行为
七、现代浏览器优化策略
1. 线程池技术
- 网络请求线程池(Chrome默认6个)
- DNS预解析线程
- 预渲染线程
2. 进程模型优化
- 站点隔离(Site Isolation):不同站点运行在不同进程
- 按需进程创建:某些扩展程序延迟加载
3. 渲染优化
- 合成层(Composite Layer):GPU加速的独立绘制层
- 光栅化策略:可视区域优先处理
八、性能监控与调试
- Performance面板:分析线程活动
- Application面板:查看Service Worker
- Memory面板:检测内存泄漏
2. 关键性能指标
- Main Thread Activity:主线程负载
- Long Tasks:超过50ms的任务
- Input Delay:输入延迟时间
3. 代码优化建议
javascript
复制代码
function chunkTask() {
// 执行小块任务
if (hasMoreWork) {
requestIdleCallback(chunkTask);
}
}
- 使用Web Animation API替代setInterval
- 避免强制同步布局(Layout Thrashing)
javascript
复制代码
// 错误示例(导致多次重排)
for (let i = 0; i < items.length; i++) {
items[i].style.width = box.offsetWidth + 'px';
}
// 正确做法(批量读取后再写入)
const width = box.offsetWidth;
for (let i = 0; i < items.length; i++) {
items[i].style.width = width + 'px';
}
九、未来发展趋势
1. WebAssembly多线程
- 共享内存(SharedArrayBuffer)
- 真正的并行计算能力
2. WebGPU
3. 更细粒度的调度API
- 调度API(Prioritized Task Scheduling)
javascript
复制代码
scheduler.postTask(() => console.log('High priority'), {
priority: 'user-blocking'
});
十、总结与最佳实践
1. 进程/线程使用原则
- 主线程:保持轻量,只处理关键UI更新
- Worker:处理CPU密集型任务
- 合理分配:根据任务类型选择执行环境
2. 性能优化检查清单
- 避免长任务阻塞主线程
- 使用requestAnimationFrame处理动画
- 将大数据处理移入Web Worker
- 合理使用内存(避免泄漏)
- 实施有效的缓存策略
3. 调试技巧
- 使用
console.time()
/performance.now()
测量执行时间
- 在DevTools中模拟低端设备
- 监控Web Worker通信开销