Fair Group Scheduling

January 14, 2020

Fair Group Scheduling とは

Fair Group Scheduling は Cgroup によるリソース管理の 1 つで、これによりプロセスグループごとに CPU 割り当て時間の制御を行うことが可能となる。
なお、Fair Group Scheduling は Linux カーネル 2.6.23 以降で導入された CFS (Completely Fair Scheduling) による機能を利用しているため、CFS が未実装のカーネルでは利用不可となる。

Fair Group Scheduling の使用方法

まず Fair Group Scheduling を利用するには cgroup ファイルシステムのマウントが必要となる。

$ sudo mount -t cgroup -o cpu cgroup /cgroup/  

今回は、CPU リソースを制御するグループを 2 つ (GroupA 及び GroupB) 作ることにする。なお、簡単のため CPU コアは 1 つのものを使用する。

$ lscpu  
Architecture:          x86_64  
CPU op-mode(s):        32-bit, 64-bit  
Byte Order:            Little Endian  
CPU(s):                1  
On-line CPU(s) list:   0  
Thread(s) per core:    1  
Core(s) per socket:    1  
Socket(s):             1  
NUMA node(s):          1  
Vendor ID:             GenuineIntel  
CPU family:            6  
Model:                 63  
Model name:            Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz  
Stepping:              2  
CPU MHz:               2399.870  
BogoMIPS:              4800.04  
Hypervisor vendor:     Xen  
Virtualization type:   full  
L1d cache:             32K  
L1i cache:             32K  
L2 cache:              256K  
L3 cache:              30720K  
NUMA node0 CPU(s):     0  
$ sudo mkdir /cgroup/GroupA  
$ sudo mkdir /cgroup/GroupB  

上記 2 つのグループにプロセスを割り振ることにより、それぞれのグループ間で CPU 時間を公平にシェアする。
まずはシェルプロセスを GroupA に割り当て、そのシェルで CPU を 100% 使用するようにする。

$ sudo sh -c "echo $$ > /cgroup/GroupA/tasks"  
$ yes > /dev/null  

同様の操作を GroupB にも施す。

$ sudo sh -c "echo $$ > /cgroup/GroupB/tasks"  
$ yes > /dev/null  

ここで、top コマンドで確認すると、50% ずつ CPU 時間が割り当てられていることがわかる。

top - 09:35:24 up 1 min,  3 users,  load average: 0.96, 0.27, 0.09  
Tasks:  85 total,   3 running,  56 sleeping,   0 stopped,   0 zombie  
Cpu(s): 48.5%us,  4.3%sy,  0.0%ni, 38.2%id,  2.1%wa,  0.0%hi,  0.2%si,  6.6%st  
Mem:   1009432k total,   486820k used,   522612k free,    18004k buffers  
Swap:        0k total,        0k used,        0k free,   377180k cached  
  
PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND  
3000 ec2-user  20   0  105m 1728 1632 R 49.8  0.2   0:33.57 yes  
3005 ec2-user  20   0  105m 1744 1648 R 49.8  0.2   0:12.76 yes  

次に、シェルを追加で 2 つ起動し、どちらも GroupB に所属させ、同様に CPU を 100% 使うようにする。つまり、GroupA には 1 プロセス、GroupB には 3 プロセス、という状況を作る (シェル自身を除く) 。

$ cat /cgroup/GroupA/tasks   
2917  
3000  
$ cat /cgroup/GroupB/tasks   
2943  
2969  
3005  
3013  
3017  
3069  

ここで top の出力を見てみると、GroupA に所属している PID 3000 のプロセスは 50% の CPU リソースを使用できているのに対して、GroupB に所属する他のプロセスは 50 % を約 3 等分する形でしか CPU リソースを使用できていないことがわかる。

top - 09:42:30 up 8 min,  5 users,  load average: 3.87, 2.48, 1.16  
Tasks:  91 total,   5 running,  62 sleeping,   0 stopped,   0 zombie  
Cpu(s): 88.2%us,  1.5%sy,  0.0%ni,  8.2%id,  0.5%wa,  0.0%hi,  0.1%si,  1.5%st  
Mem:   1009432k total,   492684k used,   516748k free,    18132k buffers  
Swap:        0k total,        0k used,        0k free,   377248k cached  
  
PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND  
3000 ec2-user  20   0  105m 1728 1632 R 49.8  0.2   4:06.31 yes  
3005 ec2-user  20   0  105m 1744 1648 R 17.9  0.2   2:39.55 yes  
3013 ec2-user  20   0  105m 1656 1560 R 15.9  0.2   0:43.41 yes  
3069 ec2-user  20   0  105m 1664 1568 R 15.9  0.2   0:22.54 yes  

cpu.shares

cpu.shares 特殊ファイルは cpu サブシステムにより提供され、プロセススケジューラで扱うプロセス群に対して割り当てる CPU 時間の重みを設定することができる。

$ ls -l /cgroup/GroupA/ | grep cpu.shares  
-rw-r--r-- 1 root root 0 Jan 14 09:48 cpu.shares  
$ cat /cgroup/GroupA/cpu.shares   
1024  

ここで、GroupB の cpu.shares を GroupA の半分である 512 に設定する。

$ sudo bash -c "echo 512 > /cgroup/GroupB/cpu.shares"  

これにより、GroupA の重みは 1024 、GroupB の重みは 512 となり、GroupA には GroupB の 2 倍の CPU 時間が割り当てられることになる。実際に top コマンドの出力を見てみるとこの設定が反映されていることがわかる。

top - 09:51:00 up 17 min,  5 users,  load average: 4.00, 3.74, 2.38  
Tasks:  91 total,   5 running,  62 sleeping,   0 stopped,   0 zombie  
Cpu(s): 93.5%us,  1.2%sy,  0.0%ni,  4.2%id,  0.2%wa,  0.0%hi,  0.0%si,  0.8%st  
Mem:   1009432k total,   492932k used,   516500k free,    18228k buffers  
Swap:        0k total,        0k used,        0k free,   377252k cached  
  
PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND  
3000 ec2-user  20   0  105m 1728 1632 R 67.7  0.2   8:32.45 yes  
3013 ec2-user  20   0  105m 1656 1560 R 11.9  0.2   2:04.72 yes  
3069 ec2-user  20   0  105m 1664 1568 R 11.9  0.2   1:43.86 yes  
3005 ec2-user  20   0  105m 1744 1648 R 10.0  0.2   4:00.86 yes  

 © 2023, Dealing with Ambiguity