We have introduced the content of CFS and group scheduling, but many people may be confused like me, next we will view the effect of CFS and group scheduling at the application level. First, for non-group scheduling, weight is the only factor that determines their running time, that is, nice we know. We can use renice to re-adjust the priority of processes, then use taskset to limit them to the same CPU (CFS only ensures the fairness of a CPU, so you can see an interesting phenomenon: for example, the cpu_allows of both processes have 3, 4, then their priority is different, and the result is that their CPU usage time is the same. What if I run another 0-level process? Then change it to level 5? -- SMP ).
Next, let's take a look at group scheduling. In order to facilitate understanding and view proc information, we create a cgroup (Mount-tcgroup-o cpu, cpuset NONE/cgroup/CPU), and then create a one group in the lower layer, and its catcpuset. CPUs = 3, cat cpuset. cpu_exclusive = 1 (that is, the processes in the cgroup only run on the CPU 3, and the CPU is exclusive ). Our example is as follows:
Figure CFS group scheduling instance
The purpose is to use this figure to calculate the CPU resources that each process (an endless process) should use, and calculate the cfs_rq load corresponding to them and their respective execution time slices, finally, verify with the information on proc.
Core Idea of group scheduling: Assign the CPU time to the ready scheduling entity (SE) below each level of group by weight ), after obtaining the time, each scheduling entity recursively allocates the ready se to it in the same way.
First, we can see from the figure that the one group manages three SE (two groups, namely onese-> my_q, three SE, one se-> cfs_rq is the se pointing to the root '/'), and so on. In addition, you can check the table prio_to_weight [], we can see that the load of the 17444 process is 335 (Nice = 5, nice = 0 load = 1024), then the se-> weight of each process. load: 17443 (1024); 17444 (335); 17445 (1024); 17446 (1024 ). Then the weights of the running queues of each group can be calculated: [Big] cfs_rq-> load = [17443] se-> weight. Load
+ [1, 17444] se-> weight. load = 1024 + 335 = 1359; [small] cfs_rq-> load = [17446] se-> weight. load = 1024; [one] cfs_rq-> load = [Big] se-> weight. load + [17445] se-> weight. load + [small] se-> weight. load = 2048 + 1024 + 512 = 3584; [/] cfs_rq-> load = [one] se-> weight. load = 1024 (this is because our CPU
3 is occupied, and other processes will not come over again, so '/' only has one se ). In this way, we can calculate the CPU usage ratio of each Se (allocated by 100%): [Big] 2048/3584; [17445] 1024/3584; [small] 512/3584; because there are two processes under big, therefore, [17443] 1024/1359*2048/3584; [17444] 335/1359*2048/3584; that is, the ratio from left to right is: 43.1%; 14.1%; 28.6%; 14.3%. From the kernel perspective, let's look at the above group relationship:
Internal Relationship of graph group scheduling
The figure corresponds to the node location. In addition, we change the corresponding fields to the kernel usage mode. In addition, the runtime slice of each process can be calculated based on these values (ideally ). Here we do not want to compute the reader. We can use the sched_slice () function method to calculate it. It should be noted that the group scheduling should be processed back to the root to get the time that the se should be executed. The result of the above nominal value can be verified by/proc/sched_debug. Considering what we mentioned above, if cpu_allows is 3, 4, and then two processes are created, what is their cfs_rq load? What is group se-> load. Weight? [Update_cfs_load, update_cfs_shares]