调度算法(一)

当进程虚拟化完成时,会自然遇到一个问题:我们该切换到哪一个进程?

人类做事情,可以依靠大脑自动完成任务的排序,比如,洗澡时,可以边想其它事边洗,可能洗完了都不知道自己刚才做了什麽。可计算机不一样,计算机很傻,它需要人来帮助它完成这一系列的安排,否则它不知道下一步该做什麽。

爲什麽是这个进程,而不是那个进程?我们的计算器是依靠什麽来决定进程的切换?

现在,是时候来好好回答一下这个问题。

先从最简单的想法开始。

先进先出队列 FIFO (First In Fisrt Out)

假设同一时间里,有多个任务,那麽,谁先到队列就先执行谁,完成后再执行下一个。

这个想法很像超市排队。实事上,这也是它被叫队列的原因,每一个任务都一样,不管你从哪里来,有什麽身份,都给我乖乖排队。

最短的先来 SJF (Shortest Job First)

可这有一点问题。虽然在计算机的眼中,这个队列怎麽排,总的运行时长是相同的,不会因爲 A 在 B 前,时间就比 B 在 A 前短。可任务不这麽想。

还是在超市排队的例子。收营员压根不管谁在前谁在后,他只负责收营,在他眼中,整个队列的时长是一定的。

但买东西的顾客就不一样了。顾客很在乎从排队开始到结算完的这段时长,因爲他们只看到了自己。每个人排了多久才完成结账的时间完全不同的。如果只有顾客 A 和 B 在排队。A 的东西要 10 分锺算完,B 要 5 分锺。如果 A 在 B 前结算,B 需要 15 分锺完成结账,反过来,B 在 A 前的话,B 只要 5 分锺就完成了。在 B 眼中,后者更高效。

你可能会说,那麽 A 不也被拖慢了,我们就不管 A 的感受了吗?

当然要管。爲此,我们应该有一个标准,来考察 B 排在 A 前比排在后,更结省每个客人的时间。

我们设置一个量,称爲 Turnaroud Time。它用来描述每一个客人从排队到完成结算的时间。比如 A 排在 B 前,那麽对于 B,它的 Turnaroud Time 是 10+5 分锺。反过来排,这个值只有 5。我们可以计算一下两种排法的期望值。

先是 A 排在 B 前。

\[10+152=12.5\cfrac{10+15}{2} = 12.5 210+15​=12.5\]

然后反过来。

\[5+152=10\cfrac{5+15}{2} = 10 25+15​=10\]

两个值并不一样!

换而言之,两种不同的排法,对期望是有影响的。在尝试一下加入第三个客人 C,它需要 15 分锺才能算完。

统计一下,不同排序对应的 Turnaroud Time 期望值。

排法 U(turnaround time)
A B C 18.333
A C B 21.667
B A C 16.667
B C A 18.333
C A B 23.333
C B A 21.557

通过 6 种不同的排列,得到的 Turnaroud Time 值是不同的。最短的,是 B A C 的顺序。

假设 B 排的是 x 分锺,对应 A 就是 2x 分锺,C 是 3x。

最短的,B A C 的顺序中,B 花了 x,A 花了 x+2x,C 花了 x+2x+3x

最长的,C A B 的顺序中,C 花了 3x,A 花了 3x+2x,B 花了 x+2x+3x

可以发现:最后一个花的时间都是相同中的,不同的是前面的人。因爲第 i+1 人花的时间,总是要加上第 i 人的时间。第 i 人花的时间越少,第 i+1 人花的时间就越少。由此,我们可以得到一个重要的规则。

最前面的任务,时长越短,Turnaroud Time 期望值越小

下面两种排法显然不同