论文英文链接: https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=805acf7726282721504c8f00575d91ebfd750564
白话说明EEVDF的实现机制:
重点讲清楚 积分(虚拟时间) 和 lag(滞后值) 是怎么算的。
EEVDF 的核心逻辑
EEVDF 的目标是让每个任务按权重比例分到 CPU 时间,同时尽量减少调度延迟。它的实现主要依赖三个关键变量:
- 权重(Weight):任务的优先级(类似 VIP 排队,权重越高越优先)。
- 虚拟时间(Virtual Time):经过权重调整后的“公平时间”。
- 合格时间(Eligible Time):任务理论上应该被调度的时刻。
举个例子
假设有两个任务:
- 任务 A:权重 2(高优先级)
- 任务 B:权重 3(更高优先级)
系统总权重 = 2 + 3 = 5。
每个调度周期内,任务 A 应分到 2/5 的资源,任务 B 应分到 3/5 的资源。
1. 虚拟时间(Virtual Time):如何按权重“算时间”?
虚拟时间 是任务的“公平时间进度条”,用来统一不同权重任务的时间单位。
核心公式:
虚拟时间增速 = 实际时间 × (N / 总权重)
- N 是当前运行队列中的任务数量。
- 总权重 是队列中所有任务的权重之和。
例子:
- 如果队列里有 A(权重 2)和 B(权重 3),总权重 = 5。
- 实际时间每过 1 秒,虚拟时间增速 = 1 × (2/5) = 0.4 秒(对 A 来说)
或者 1 × (3/5) = 0.6 秒(对 B 来说)。
这意味着:
- 权重高的任务(B)虚拟时间走得更快,看起来“更耗时”,从而让调度器认为它需要更多实际时间(公平性)。
- 权重低的任务(A)虚拟时间走得更慢,显得“更轻松”,调度器会多分给它实际时间。
2. 合格时间(Eligible Time):什么时候该轮到我?
合格时间 是任务理论上应该被调度的时刻,计算公式:
合格时间 = 上次调度时间 + (需要运行的实际时间 × 总权重 / 当前队列总权重)
例子:
- 任务 A 需要运行 1 秒实际时间,当前队列总权重 5。
它的合格时间 = 当前时间 + (1 × 5 / 5) = 当前时间 + 1 秒。
(即:它认为自己需要 1 秒就能完成,但实际可能因为权重被延迟)
3. 拉格(Lag):我到底落后了多少?
拉格(Lag) 是任务实际已消耗时间与虚拟时间之间的差值,用来判断任务是否被饿死。
计算方式:
拉格 = 实际已运行时间 - 虚拟时间
例子:
- 任务 A 的虚拟时间是 0.4 秒(按权重计算),但实际已经跑了 1 秒。
拉格 = 1 - 0.4 = **+0.6 秒** → 说明它落后了,应该优先调度。 - 如果拉格为负数,说明任务已经超前,可以延后调度。
4. 调度策略:怎么决定下一个调度的任务?
EEVDF 每次选择 拉格最大 的任务来调度(谁最亏就先补谁)。
同时,结合 合格时间 确保任务不会无限期等待。
具体步骤:
- 计算每个任务的 虚拟时间 和 合格时间。
- 计算每个任务的 拉格(实际时间 - 虚拟时间)。
- 选择 拉格最大且合格时间最早 的任务执行。
举个完整例子
假设系统里有任务 A(权重 2)和 B(权重 3):
- 初始状态:
- A 和 B 都刚启动,虚拟时间 = 0,合格时间 = 0。
- 第一次调度:
- 两者拉格都为 0,但合格时间相同。
- EEVDF 会选权重更高的 B(因为权重高,虚拟时间增速快,拉格增长更快)。
- B 运行一段时间后:
- B 的虚拟时间增速是 0.6 秒/实际秒,假设实际跑了 1 秒,虚拟时间变为 0.6 秒。
- B 的拉格 = 实际时间(1秒) - 虚拟时间(0.6秒) = +0.4 秒。
- 此时 A 的虚拟时间:
- 实际时间过了 1 秒,A 的虚拟时间增速是 0.4 秒/实际秒 → 虚拟时间 = 0.4 秒。
- A 的拉格 = 1秒(实际) - 0.4秒(虚拟) = +0.6 秒。
- 第二次调度:
- A 的拉格更大(+0.6 > B 的 +0.4),所以优先调度 A。
总结
- 虚拟时间:让不同权重的任务在“公平时间”下统一进度。
- 拉格:衡量任务是否被饿死,越亏越优先调度。
- 合格时间:防止某个任务无限期等待,结合时间片轮转。
EEVDF 通过这种机制,既保证了权重比例(高权重任务长期分到更多时间),又避免了低权重任务被饿死(短期及时补偿)。