完整架构图
┌─────────────────────────────────────────────────────────────────────┐
│ React 调度系统完整架构图 │
└─────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════
第 1 层:任务调度层(Update Queue)
═══════════════════════════════════════════════════════════════════════
用户操作/事件
↓
┌──────────────────────────────────────┐
│ 创建更新(Update) │
│ - setState(1) → InputLane │
│ - startTransition → TransitionLane │
└──────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ 任务队列(按优先级) │
├──────────────────────────────────────┤
│ Update A: InputLane (高) │
│ Update B: DefaultLane (中) │
│ Update C: TransitionLane (低) │
└──────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ 选择最高优先级 Update │
│ getNextLanes(root) │
└──────────────────────────────────────┘
↓
═══════════════════════════════════════════════════════════════════════
第 2 层:时间切片层(Scheduler)
═══════════════════════════════════════════════════════════════════════
┌──────────────────────────────────────┐
│ 开始执行 Update A │
│ 设置时间切片:5ms │
│ deadline = now + 5 │
└──────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ 工作循环(workLoop) │
│ │
│ while (workInProgress) { │
│ ┌─ 检查 1: 有更高优先级? │
│ │ → Yes: 中断,重新调度 │
│ │ → No: 继续 │
│ │ │
│ ├─ 检查 2: 时间到了? │
│ │ → Yes: 让出控制权 │
│ │ → No: 继续 │
│ │ │
│ └─ 处理一个 Fiber 节点 │
│ } │
└──────────────────────────────────────┘
↓
═══════════════════════════════════════════════════════════════════════
第 3 层:Fiber 执行层(Reconciliation)
═══════════════════════════════════════════════════════════════════════
┌──────────────────────────────────────────────────┐
│ 为 Update A 构建 Fiber 树 │
│ │
│ workInProgress 树(双缓存) │
│ ┌─────┐ │
│ │Root │ │
│ └──┬──┘ │
│ ┌────────┴────────┐ │
│ ┌──▼──┐ ┌──▼──┐ │
│ │App │ │null │ │
│ └──┬──┘ └─────┘ │
│ ┌────┴────┐ │
│ ┌─▼──┐ ┌─▼──┐ │
│ │Hdr │ │Body│ │
│ └────┘ └────┘ │
│ │
│ 链表遍历:child → sibling → return │
└──────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ 处理每个 Fiber 节点 │
│ performUnitOfWork(fiber) │
│ - Diff 算法 │
│ - 标记副作用 (flags) │
│ - 计算新状态 │
└──────────────────────────────────────┘
↓
═══════════════════════════════════════════════════════════════════════
第 4 层:提交层(Commit)
═══════════════════════════════════════════════════════════════════════
┌──────────────────────────────────────┐
│ Fiber 树构建完成 │
└──────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ 提交阶段(不可中断) │
│ commitRoot() │
│ 1. Before Mutation │
│ 2. Mutation (更新 DOM) │
│ 3. 切换指针 ◄────── 双缓存 │
│ root.current = workInProgress │
│ 4. Layout (useEffect) │
└──────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ 用户看到更新 ✅ │
└──────────────────────────────────────┘
时间轴视图:三者配合
时间 │ 任务调度 │ 时间切片 │ Fiber 处理
─────┼──────────────────┼──────────────────┼─────────────────
0ms │ 选择 Update A │ 设置 deadline │
│ (高优先级) │ = 5ms │
─────┼──────────────────┼──────────────────┼─────────────────
1ms │ │ 执行中... │ 处理 Fiber 1
2ms │ │ 执行中... │ 处理 Fiber 2
3ms │ │ 执行中... │ 处理 Fiber 3
4ms │ │ 执行中... │ 处理 Fiber 4
5ms │ │ 时间到!让出 │ 暂停
─────┼──────────────────┼──────────────────┼─────────────────
6ms │ │ 浏览器处理输入 │
─────┼──────────────────┼──────────────────┼─────────────────
7ms │ 检查队列 │ 设置新切片 │ 继续 Fiber 5
│ 仍是 Update A │ deadline = 12ms │
8ms │ │ 执行中... │ 处理 Fiber 6
─────┼──────────────────┼──────────────────┼─────────────────
9ms │ 新增 Update B! │ │ 处理 Fiber 7
│ (更高优先级) │ │
10ms │ 检测到更高优先级 │ 中断! │ 丢弃 workInProgress
─────┼──────────────────┼──────────────────┼─────────────────
11ms │ 切换到 Update B │ 设置新切片 │ 开始新 Fiber 树
│ │ deadline = 16ms │ 处理 Fiber 1
12ms │ │ │ 处理 Fiber 2
13ms │ │ │ 完成!提交
─────┼──────────────────┼──────────────────┼─────────────────
14ms │ 回到 Update A │ 设置新切片 │ 重新开始 Fiber 树
│ │ │ (基于新的 current)
优先级中断示意图
正在处理低优先级 Update
│
│ ┌─────────────────────────────────┐
│ │ Fiber 树 A (低优先级) │
│ │ ✓ Fiber 1 ✓ Fiber 2 │
│ │ ✓ Fiber 3 → Fiber 4 (执行中) │
│ └─────────────────────────────────┘
│
↓ 高优先级 Update 插入!
│
├─ 检测优先级 → 中断
│
├─ 丢弃 Fiber 树 A ❌
│
↓
│ ┌─────────────────────────────────┐
│ │ Fiber 树 B (高优先级) │
│ │ Fiber 1 → Fiber 2 → Fiber 3 │
│ │ ✓ 完成 → 提交 → 显示 ✅ │
│ └─────────────────────────────────┘
│
↓ 回来处理低优先级
│
│ ┌─────────────────────────────────┐
│ │ Fiber 树 A' (基于新 current) │
│ │ 重新构建整棵树 │
│ │ Fiber 1 → Fiber 2 → ... │
│ │ ✓ 完成 → 提交 → 显示 ✅ │
│ └─────────────────────────────────┘
层次关系图
┌─────────────────────────────────────┐
│ 层次 1:Update(更新/任务) │ ← 最高维度
│ ━━━━━━━━━━━━━━━━━━━━━━━━ │
│ - 有优先级(lane) │
│ - 有过期时间 │
│ - 保存在队列中 │
│ - 决定"做什么" │
└─────────────────────────────────────┘
↓ 执行时产生
┌─────────────────────────────────────┐
│ 层次 2:Fiber 树(workInProgress) │ ← 执行产物
│ ━━━━━━━━━━━━━━━━━━━━━━━━ │
│ - 执行更新时构建的 │
│ - 可以被丢弃 │
│ - 完成后提交 │
│ - 决定"如何做" │
└─────────────────────────────────────┘
↓ 由节点组成
┌─────────────────────────────────────┐
│ 层次 3:Fiber 节点 │ ← 最小单元
│ ━━━━━━━━━━━━━━━━━━━━━━━━ │
│ - 树的组成单元 │
│ - 链表连接 │
│ - 工作的最小粒度 │
└─────────────────────────────────────┘
映射关系:
1 个 Update = 1 次渲染 = 1 棵 Fiber 树 = N 个 Fiber 节点
核心机制总结
任务调度(Update Scheduling)
作用:决定"做什么"
机制:优先级队列 + 过期时间
单位:Update(状态更新)
输出:选择一个 Update 执行
核心代码:
function scheduleUpdateOnFiber(fiber, lane) {
// 标记优先级到 root
root.pendingLanes |= lane;
// 选择最高优先级
const nextLane = getNextLanes(root);
// 开始调度
ensureRootIsScheduled(root, nextLane);
}
时间切片(Time Slicing)
作用:决定"做多久"
机制:5ms 切片 + shouldYield 检查
控制:让出浏览器控制权
输出:执行一段时间后主动暂停
核心代码:
function workLoop() {
deadline = now + 5; // 5ms 切片
while (workInProgress && !shouldYield()) {
performUnitOfWork(workInProgress);
}
if (workInProgress) {
port.postMessage(null); // 让出控制权
}
}
Fiber 架构(Fiber Tree)
作用:决定"如何做"
机制:链表结构 + 可中断遍历
单位:Fiber 节点
输出:构建完整的 workInProgress 树
核心代码:
function performUnitOfWork(fiber) {
// 处理当前节点
reconcile(fiber);
// 返回下一个节点(深度优先)
if (fiber.child) return fiber.child;
if (fiber.sibling) return fiber.sibling;
return fiber.return;
}
完整执行流程
1. 用户触发更新
onClick={() => setState(1)}
↓
2. 创建 Update 对象
Update { lane: InputLane, payload: 1 }
↓
3. 加入任务队列
root.pendingLanes |= InputLane
↓
4. 调度器选择最高优先级任务
const nextLane = getNextLanes(root)
↓
5. 设置时间切片
deadline = now + 5ms
↓
6. 开始构建 Fiber 树
workInProgress = createWorkInProgress(current)
↓
7. 循环处理 Fiber 节点
while (workInProgress) {
// 检查优先级
if (hasHigherPriority) break;
// 检查时间
if (shouldYield) break;
// 处理节点
performUnitOfWork(workInProgress);
}
↓
8. 完成后提交
commitRoot(workInProgress)
↓
9. 切换双缓存
root.current = workInProgress
↓
10. 用户看到更新
关键检查点
检查点 1:优先级检查
function renderRoot(root, currentLane) {
while (workInProgress) {
const nextLanes = getNextLanes(root);
if (nextLanes !== currentLane && nextLanes < currentLane) {
// 有更高优先级 → 中断
workInProgress = null;
return;
}
performUnitOfWork(workInProgress);
}
}
检查点 2:时间切片检查
function workLoop() {
while (workInProgress && !shouldYield()) {
performUnitOfWork(workInProgress);
}
}
function shouldYield() {
return performance.now() >= deadline;
}
检查点 3:过期检查
function markStarvedLanesAsExpired(root) {
const now = performance.now();
pendingLanes.forEach(lane => {
if (expirationTime[lane] <= now) {
// 过期了 → 提升为最高优先级
root.expiredLanes |= lane;
}
});
}
三者协作关系
┌──────────────────────────────────────────────────┐
│ 三者协作模式 │
└──────────────────────────────────────────────────┘
任务调度 ──控制→ 时间切片 ──调度→ Fiber 执行
↑ │
└──────── 检查优先级 ←───────────┘
详细说明:
1. 任务调度 → 时间切片
- 选择最高优先级任务
- 设置执行时间限制
2. 时间切片 → Fiber 执行
- 在时间限制内处理 Fiber 节点
- 时间到了主动让出
3. Fiber 执行 → 任务调度
- 每处理一个节点检查优先级
- 发现更高优先级通知调度器
核心要点
三者定位:
- 任务调度:最高层,管理所有 Update,决定执行顺序
- 时间切片:中间层,控制执行时长,保证响应性
- Fiber:最底层,具体执行单元,可中断可恢复
协作实现:可中断的优先级渲染
- 任务调度保证紧急的先做
- 时间切片保证浏览器能响应
- Fiber 架构保证可以中断和恢复
最终目标:流畅的用户体验