-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 96191 b: refs/heads/master c: dc5dc7e h: refs/heads/master i: 96189: 997416b 96187: 764adad 96183: 018d2c8 96175: ae43732 96159: 16f6fd8 96127: be75440 v: v3
- Loading branch information
David S. Miller
committed
May 8, 2008
1 parent
37e6885
commit 95ef6ed
Showing
244 changed files
with
2,591 additions
and
4,207 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 8d539108560ec121d59eee05160236488266221c | ||
refs/heads/master: dc5dc7e6d71ca9fd1ea01a1418150af3b2937489 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
Goals, Design and Implementation of the | ||
new ultra-scalable O(1) scheduler | ||
|
||
|
||
This is an edited version of an email Ingo Molnar sent to | ||
lkml on 4 Jan 2002. It describes the goals, design, and | ||
implementation of Ingo's new ultra-scalable O(1) scheduler. | ||
Last Updated: 18 April 2002. | ||
|
||
|
||
Goal | ||
==== | ||
|
||
The main goal of the new scheduler is to keep all the good things we know | ||
and love about the current Linux scheduler: | ||
|
||
- good interactive performance even during high load: if the user | ||
types or clicks then the system must react instantly and must execute | ||
the user tasks smoothly, even during considerable background load. | ||
|
||
- good scheduling/wakeup performance with 1-2 runnable processes. | ||
|
||
- fairness: no process should stay without any timeslice for any | ||
unreasonable amount of time. No process should get an unjustly high | ||
amount of CPU time. | ||
|
||
- priorities: less important tasks can be started with lower priority, | ||
more important tasks with higher priority. | ||
|
||
- SMP efficiency: no CPU should stay idle if there is work to do. | ||
|
||
- SMP affinity: processes which run on one CPU should stay affine to | ||
that CPU. Processes should not bounce between CPUs too frequently. | ||
|
||
- plus additional scheduler features: RT scheduling, CPU binding. | ||
|
||
and the goal is also to add a few new things: | ||
|
||
- fully O(1) scheduling. Are you tired of the recalculation loop | ||
blowing the L1 cache away every now and then? Do you think the goodness | ||
loop is taking a bit too long to finish if there are lots of runnable | ||
processes? This new scheduler takes no prisoners: wakeup(), schedule(), | ||
the timer interrupt are all O(1) algorithms. There is no recalculation | ||
loop. There is no goodness loop either. | ||
|
||
- 'perfect' SMP scalability. With the new scheduler there is no 'big' | ||
runqueue_lock anymore - it's all per-CPU runqueues and locks - two | ||
tasks on two separate CPUs can wake up, schedule and context-switch | ||
completely in parallel, without any interlocking. All | ||
scheduling-relevant data is structured for maximum scalability. | ||
|
||
- better SMP affinity. The old scheduler has a particular weakness that | ||
causes the random bouncing of tasks between CPUs if/when higher | ||
priority/interactive tasks, this was observed and reported by many | ||
people. The reason is that the timeslice recalculation loop first needs | ||
every currently running task to consume its timeslice. But when this | ||
happens on eg. an 8-way system, then this property starves an | ||
increasing number of CPUs from executing any process. Once the last | ||
task that has a timeslice left has finished using up that timeslice, | ||
the recalculation loop is triggered and other CPUs can start executing | ||
tasks again - after having idled around for a number of timer ticks. | ||
The more CPUs, the worse this effect. | ||
|
||
Furthermore, this same effect causes the bouncing effect as well: | ||
whenever there is such a 'timeslice squeeze' of the global runqueue, | ||
idle processors start executing tasks which are not affine to that CPU. | ||
(because the affine tasks have finished off their timeslices already.) | ||
|
||
The new scheduler solves this problem by distributing timeslices on a | ||
per-CPU basis, without having any global synchronization or | ||
recalculation. | ||
|
||
- batch scheduling. A significant proportion of computing-intensive tasks | ||
benefit from batch-scheduling, where timeslices are long and processes | ||
are roundrobin scheduled. The new scheduler does such batch-scheduling | ||
of the lowest priority tasks - so nice +19 jobs will get | ||
'batch-scheduled' automatically. With this scheduler, nice +19 jobs are | ||
in essence SCHED_IDLE, from an interactiveness point of view. | ||
|
||
- handle extreme loads more smoothly, without breakdown and scheduling | ||
storms. | ||
|
||
- O(1) RT scheduling. For those RT folks who are paranoid about the | ||
O(nr_running) property of the goodness loop and the recalculation loop. | ||
|
||
- run fork()ed children before the parent. Andrea has pointed out the | ||
advantages of this a few months ago, but patches for this feature | ||
do not work with the old scheduler as well as they should, | ||
because idle processes often steal the new child before the fork()ing | ||
CPU gets to execute it. | ||
|
||
|
||
Design | ||
====== | ||
|
||
The core of the new scheduler contains the following mechanisms: | ||
|
||
- *two* priority-ordered 'priority arrays' per CPU. There is an 'active' | ||
array and an 'expired' array. The active array contains all tasks that | ||
are affine to this CPU and have timeslices left. The expired array | ||
contains all tasks which have used up their timeslices - but this array | ||
is kept sorted as well. The active and expired array is not accessed | ||
directly, it's accessed through two pointers in the per-CPU runqueue | ||
structure. If all active tasks are used up then we 'switch' the two | ||
pointers and from now on the ready-to-go (former-) expired array is the | ||
active array - and the empty active array serves as the new collector | ||
for expired tasks. | ||
|
||
- there is a 64-bit bitmap cache for array indices. Finding the highest | ||
priority task is thus a matter of two x86 BSFL bit-search instructions. | ||
|
||
the split-array solution enables us to have an arbitrary number of active | ||
and expired tasks, and the recalculation of timeslices can be done | ||
immediately when the timeslice expires. Because the arrays are always | ||
access through the pointers in the runqueue, switching the two arrays can | ||
be done very quickly. | ||
|
||
this is a hybride priority-list approach coupled with roundrobin | ||
scheduling and the array-switch method of distributing timeslices. | ||
|
||
- there is a per-task 'load estimator'. | ||
|
||
one of the toughest things to get right is good interactive feel during | ||
heavy system load. While playing with various scheduler variants i found | ||
that the best interactive feel is achieved not by 'boosting' interactive | ||
tasks, but by 'punishing' tasks that want to use more CPU time than there | ||
is available. This method is also much easier to do in an O(1) fashion. | ||
|
||
to establish the actual 'load' the task contributes to the system, a | ||
complex-looking but pretty accurate method is used: there is a 4-entry | ||
'history' ringbuffer of the task's activities during the last 4 seconds. | ||
This ringbuffer is operated without much overhead. The entries tell the | ||
scheduler a pretty accurate load-history of the task: has it used up more | ||
CPU time or less during the past N seconds. [the size '4' and the interval | ||
of 4x 1 seconds was found by lots of experimentation - this part is | ||
flexible and can be changed in both directions.] | ||
|
||
the penalty a task gets for generating more load than the CPU can handle | ||
is a priority decrease - there is a maximum amount to this penalty | ||
relative to their static priority, so even fully CPU-bound tasks will | ||
observe each other's priorities, and will share the CPU accordingly. | ||
|
||
the SMP load-balancer can be extended/switched with additional parallel | ||
computing and cache hierarchy concepts: NUMA scheduling, multi-core CPUs | ||
can be supported easily by changing the load-balancer. Right now it's | ||
tuned for my SMP systems. | ||
|
||
i skipped the prev->mm == next->mm advantage - no workload i know of shows | ||
any sensitivity to this. It can be added back by sacrificing O(1) | ||
schedule() [the current and one-lower priority list can be searched for a | ||
that->mm == current->mm condition], but costs a fair number of cycles | ||
during a number of important workloads, so i wanted to avoid this as much | ||
as possible. | ||
|
||
- the SMP idle-task startup code was still racy and the new scheduler | ||
triggered this. So i streamlined the idle-setup code a bit. We do not call | ||
into schedule() before all processors have started up fully and all idle | ||
threads are in place. | ||
|
||
- the patch also cleans up a number of aspects of sched.c - moves code | ||
into other areas of the kernel where it's appropriate, and simplifies | ||
certain code paths and data constructs. As a result, the new scheduler's | ||
code is smaller than the old one. | ||
|
||
Ingo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.