はじめに
cgroupsは、cpu時間やメモリなどのリソース(これらの単一のリソースはサブシステムと呼ばれる)をユーザ指定のプロセスに割り当てることができるLinuxの仕組みです。身近なところでは、Dockerコンテナへのリソース割当においてcgroupsが利用されているようです。また、cgroupsは、プログラムの実行時間とリソース割当の関係を見積もる際にも役立ちます。
本記事は、カウントアップのプログラムを題材にして、cgroupsによってcpu時間とメモリを制限されたプログラムの実行時間を計測したものです。
対象読者
・プログラムの実行時間とリソースの関係を把握したい方
前提条件
OS : Ubuntu 20.04
Kernel : 5.15.0-52-generic
1. 準備
1.1 cgroup-toolsのインストール
cgroup-toolsをインストールします。
# sudo apt install cgroup-tools
1.2 リソース割当に関するパラメータ設定と反映
/etc/cgconfig.confにリソース割当に関するパラメータを設定していきます。
cpu.cfs_period_usはcpu時間の割当周期を指定するパラメータです。
cpu.cfs_quota_usはプロセスが使用するコア全体で占有するcpu時間を指定するパラメータです。注意事項としては、例えば、プロセスが2コアを使用する場合、単一コアの使用時間は、cpu.cfs_quota_usとして設定した値の半分になります。従って、下記の設定値の場合、単一コアのcpu利用時間は、125000[us]となります。
memory.limit_in_bytesは利用可能なメモリの最大値を指定するパラメータです。
# vi /etc/cgconfig.conf
group mycgr1{
cpu {
cpu.cfs_quota_us = 250000;
cpu.cfs_period_us = 1000000;
}
memory {
memory.limit_in_bytes = 1M;
}
cpuacct {
}
}
下記のコマンドでパラメータを反映させます。
# cgconfigparser -l /etc/cgconfig.conf
1.3 動作確認
先ずは、cgroupsを使わない場合のストレステストを実施します。
# sudo stress -c 2
stress: info: [3665] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
2コアともに、cpu使用率が100%近くになっています。
# top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3667 root 20 0 3864 96 0 R 100.0 0.0 0:21.28 stress
3666 root 20 0 3864 96 0 R 99.7 0.0 0:21.24 stress
次に、cgroupsを使った場合のストレステストを実施します。
# sudo cgexec -g cpu,memory:mycgr1 stress -c 2
stress: info: [3673] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
2コアを利用しているため、単一コアのcpu使用率は12.5%程度になっています。設定したパラメータから期待されるcpu使用率と一致しているため、正常に動作していると言えます。
# top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3675 root 20 0 3864 100 0 R 12.6 0.0 0:02.20 stress
3674 root 20 0 3864 100 0 R 12.3 0.0 0:02.20 stress
2. 試験
cgroupsにてcpu利用率やメモリを制限しながら、カウントアップするプログラムの実行時間を計測していきます。
2.1 カウントアップ・プログラムの作成
100万までカウントアップするプログラムを作成しました。
#!/bin/bash
a=$(date "+%s")
k=0
for i in `seq 1000000 -1 1`
do
k=$(($k+1))
done
b=$(date "+%s")
echo "Cout Value:"$k
echo "Elapsed Time:"$((b-a))"[sec]"
test.shに実行権限を与えて実行すると、カウンターの値と実行時間が表示されます。尚、このときのcpu使用率は100%となり、実行時間は2秒でした。
# ./test.sh
Cout Value:1000000
Elapsed Time:2[sec]
2.2 cgroupsによるリソース制限とプログラム実行時間の関係
2.2.1 cpu利用率を25%に制限した場合
cpu利用率25%にした場合のプログラム実行時間を計測しました。
下記コマンドでプログラムを実行した後のプログラム実行時間は8秒となっていました。cpu利用率が100%の場合は2秒であったため、実行時間が4倍になっているのは妥当と言えます。
# sudo cgexec -g cpu:mycgr1 ./test.sh
Cout Value:1000000
Elapsed Time:8[sec]
2.2.2 メモリを1MBに制限した場合
メモリを1MB割り当てた場合のプログラム実行時間を計測しました。
下記コマンドで実行した後のプログラム実行時間は15秒となっていました。メモリが少なすぎるために、プログラムの速度が低下してしまったと考えられます。
# sudo cgexec -g memory:mycgr1 ./test.sh
Cout Value:1000000
Elapsed Time:15[sec]
2.2.3 cpu利用率を25%、メモリを1MBに制限した場合
cpu利用率を25%、メモリを1MBにした場合のプログラム実行時間を計測しました。
下記コマンドで実行した後のプログラム実行時間は41秒となっており、cpuとメモリのリソースが共に制限されているために実行時間がより長くなってしまったと考えられます。
# sudo cgexec -g cpu,memory:mycgr1 ./test.sh
Cout Value:1000000
Elapsed Time:41[sec]
3. まとめ
本記事では、cgroupsを用いることで、プログラムの実行時間とリソース割当の関係を把握できることを示しました。
参考文献
おまけ
/sys/fs/cgroup/の配下には、収集した統計情報などが格納されています。
# ls /sys/fs/cgroup/
blkio cpu,cpuacct freezer misc net_prio rdma
cpu cpuset hugetlb net_cls perf_event systemd
cpuacct devices memory net_cls,net_prio pids unified