Weighting (Niceness)

This lesson will make you familiar with the concept of weighting (niceness) with the discussion of an example.

We'll cover the following

Nice level of a process

CFS also enables controls over process priority, enabling users or administrators to give some processes a higher share of the CPU. It does this not with tickets, but through a classic UNIX mechanism known as the nice level of a process. The nice parameter can be set anywhere from -20 to +19 for a process, with a default of 0. Positive nice values imply lower priority and negative values imply higher priority; when you’re too nice, you just don’t get as much (scheduling) attention, alas.

CFS maps the nice value of each process to a weight, as shown here:

Press + to interact
static const int prio_to_weight[40] = {
/* -20 */ 88761, 71755, 56483, 46273, 36291,
/* -15 */ 29154, 23254, 18705, 14949, 11916,
/* -10 */ 9548, 7620, 6100, 4904, 3906,
/* -5 */ 3121, 2501, 1991, 1586, 1277,
/* 0 */ 1024, 820, 655, 526, 423,
/* 5*/ 335, 272, 215, 172, 137,
/* 10 */ 110, 87, 70, 56, 45,
/*15*/ 36, 29, 23, 18, 15,
};

These weights allow us to compute the effective time slice of each process (as we did before), but now accounting for their priority differences. The formula used to do so is as follows:

timeslicektimeslice_k = 􏰀weightki=0n1weighti\frac {weight_k}{\sum_{i=0}^{n-1} {weight_i}} · sched_latencysched\_latency

Example

Let’s do an example to see how this works. Assume there are two jobs, A and B. A, because it’s our most precious job, is given a higher priority by assigning it a nice value of -5; B, because we hates itYes, yes, we are using bad grammar here on purpose, please don’t send in a bug fix. Why? Well, just a most mild of references to the Lord of the Rings, and our favorite anti-hero Gollum, nothing to get too excited about., just has the default priority (nice value equal to 0). This means weightAweight_A (from the table) is 3121, whereas weightBweight_B is 1024. If you then compute the time slice of each job, you’ll find that A’s time slice is about 34\frac 3 4 of sched_latency (hence, 36 ms), and B’s about 14\frac 1 4 (hence, 12 ms).

In addition to generalizing the time slice calculation, the way CFS calculates vruntime must also be adapted. Here is the new formula, which takes the actual run time that process ii has accrued (runtimeiruntime_i) and scales it inversely by the weight of the process. In our running example, A’s vruntime will accumulate at one-third the rate of B’s.

vruntimei=vruntimei+vruntime_i = vruntime_i + weight0weighti.runtimei\frac {weight_0} {weight_i} .runtime_i

One smart aspect of the construction of the table of weights above is that the table preserves CPU proportionality ratios when the difference in nice values is constant. For example, if process A instead had a nice value of 5 (not -5), and process B had a nice value of 10 (not 0), CFS would schedule them in exactly the same manner as before. Run through the math yourself to see why.

Get hands-on with 1400+ tech skills courses.