Memory Cgroup

February 04, 2020

Memory Cgroup とは

Memory Cgroup は Cgroup の 1 つで、プロセスが使用するメモリの量をコントロールするためのものとなる。
例えば、一時的に大きなファイル (もしくは大量のファイル) を扱うことによって発生する不要なページキャッシュ増大によるメモリ圧迫を回避するといった使い方が考えられる。また、マルチユーザー環境にて、ユーザー毎にメモリに対して Quota を設定するという使用方法も考えられる。

使い方

Memory Cgroup を使用するには cgroup ファイルシステムのマウントが必要となる。

$ sudo mount -t cgroup -o memory memcg /cgroup/  
$ ls -l /cgroup/  
total 0  
-rw-r--r-- 1 root root 0 Feb  4 01:39 cgroup.clone_children  
--w--w--w- 1 root root 0 Feb  4 01:39 cgroup.event_control  
-rw-r--r-- 1 root root 0 Feb  4 01:39 cgroup.procs  
-r--r--r-- 1 root root 0 Feb  4 01:39 cgroup.sane_behavior  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.failcnt  
--w------- 1 root root 0 Feb  4 01:39 memory.force_empty  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.failcnt  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.limit_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.max_usage_in_bytes  
-r--r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.slabinfo  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.tcp.failcnt  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.tcp.limit_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.tcp.max_usage_in_bytes  
-r--r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.tcp.usage_in_bytes  
-r--r--r-- 1 root root 0 Feb  4 01:39 memory.kmem.usage_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.limit_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.max_usage_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.memsw.failcnt  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.memsw.limit_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.memsw.max_usage_in_bytes  
-r--r--r-- 1 root root 0 Feb  4 01:39 memory.memsw.usage_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.move_charge_at_immigrate  
-r--r--r-- 1 root root 0 Feb  4 01:39 memory.numa_stat  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.oom_control  
---------- 1 root root 0 Feb  4 01:39 memory.pressure_level  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.soft_limit_in_bytes  
-r--r--r-- 1 root root 0 Feb  4 01:39 memory.stat  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.swappiness  
-r--r--r-- 1 root root 0 Feb  4 01:39 memory.usage_in_bytes  
-rw-r--r-- 1 root root 0 Feb  4 01:39 memory.use_hierarchy  
-rw-r--r-- 1 root root 0 Feb  4 01:39 notify_on_release  
-rw-r--r-- 1 root root 0 Feb  4 01:39 release_agent  
-rw-r--r-- 1 root root 0 Feb  4 01:39 tasks  

なお、Memory Cgroup 関連の主な特殊ファイルは以下の通りとなる。

ファイル名 説明
memory.usage_in_bytes 現在のメモリ (プロセスメモリ + ページキャッシュ) 使用量の表示
memory.memsw.usage_in_bytes 現在のメモリ (プロセスメモリ + ページキャッシュ) + スワップ使用量の表示
memory.limit_in_bytes メモリ (プロセスメモリ + ページキャッシュ) 使用量の制限値の設定* 表示
memory.memsw.limit_in_bytes メモリ (プロセスメモリ + ページキャッシュ) + スワップ使用量の制限値の設定* 表示
memory.failcnt メモリ (プロセスメモリ + ページキャッシュ) が制限値に達した回数の表示
memory.memsw.failcnt メモリ (プロセスメモリ + ページキャッシュ) + スワップが制限値に達した回数の表示
memory.max_usage_in_bytes 記録されたメモリ (プロセスメモリ + ページキャッシュ) 使用量の最大値の表示
memory.memsw.max_usage_in_bytes 記録されたメモリ (プロセスメモリ + ページキャッシュ) + スワップ使用量の最大値の表示
memory.stat 統計情報の出力
memory.force_empty グループに割り当てられているメモリの強制解放
memory.use_hierarchy 階層構造使用の設定* 表示
memory.swappiness グループに対する swappiness (sysctl の vm.swappiness 相当) の設定* 表示

メモリ使用量を制限する

実際にメモリ使用量を制限するには、memory.limit_in_bytes を使用する。ここでは GroupA という名のグループを作成し、メモリ使用量の制限を 10 MB とする。

$ sudo mkdir /cgroup/GroupA  
$ sudo bash -c "echo 10M > /cgroup/GroupA/memory.limit_in_bytes"  
$ sudo bash -c "echo $$ > /cgroup/GroupA/tasks"  

それでは実際に大きなファイルを取得し、メモリの使用量がどう変わるのかを見てみる。

[ メモリ使用量制限無しの場合 ]

$ free  
             total       used       free     shared    buffers     cached  
Mem:      64463556     564504   63899052         68      82124     221468  
-/+ buffers/cache:     260912   64202644  
Swap:            0          0          0  
  
$ wget https://buildlogs.centos.org/centos/7/isos/x86_64/CentOS-7-livecd-x86_64.iso  
--2020-02-04 05:00:45--  https://buildlogs.centos.org/centos/7/isos/x86_64/CentOS-7-livecd-x86_64.iso  
Resolving buildlogs.centos.org (buildlogs.centos.org)... 162.254.149.130, 2604:4500:0:109::10  
Connecting to buildlogs.centos.org (buildlogs.centos.org)|162.254.149.130|:443... connected.  
HTTP request sent, awaiting response... 200 OK  
Length: 719323136 (686M) [application/octet-stream]  
Saving to: 'CentOS-7-livecd-x86_64.iso'  
  
CentOS-7-livecd-x86_64.iso                           100%[======================================================================================================================>] 686.00M   555KB/s    in 21m 55s   
  
2020-02-04 05:22:41 (534 KB/s) - 'CentOS-7-livecd-x86_64.iso' saved [719323136/719323136]  
  
$ free  
             total       used       free     shared    buffers     cached  
Mem:      64463556    1286992   63176564         68      82156     924036  
-/+ buffers/cache:     280800   64182756  
Swap:            0          0          0  

-> 約 700 MB がファイルキャッシュとして使用されていることがわかる。

それでは一旦先ほどダウンロードしたファイルを削除し、ファイルキャッシュを消した上で GroupA に所属するプロセス (bash) から再度同様のコマンドを実施する。
ちなみに以下の用量で一旦 swap をオンにした。(じゃないと途中で使用可能なメモリがなくなってプロセスが死ぬ)

$ sudo dd if=/dev/zero of=/swapfile bs=128M count=32  
32+0 records in  
32+0 records out  
4294967296 bytes (4.3 GB) copied, 2.57173 s, 1.7 GB/s  
$ sudo chmod 600 /swapfile  
$ sudo mkswap /swapfile  
Setting up swapspace version 1, size = 4194300 KiB  
no label, UUID=a194c7c2-50cf-40b6-8488-d8c2a5a3ce4f  
$ sudo swapon /swapfile  
$ sudo swapon -s  
Filename		   	       Type		Size	Used	Priority  
/swapfile                              			file	4194300	0	-2  

[ メモリ使用量制限有りの場合 ]

$ free  
             total       used       free     shared    buffers     cached  
Mem:      64463556    4895240   59568316         68      82820    4429092  
-/+ buffers/cache:     383328   64080228  
Swap:      4194300          0    4194300  
  
$ wget https://buildlogs.centos.org/centos/7/isos/x86_64/CentOS-7-livecd-x86_64.iso  
--2020-02-04 05:50:21--  https://buildlogs.centos.org/centos/7/isos/x86_64/CentOS-7-livecd-x86_64.iso  
Resolving buildlogs.centos.org (buildlogs.centos.org)... 38.110.33.4, 2607:1680:0:1::2  
Connecting to buildlogs.centos.org (buildlogs.centos.org)|38.110.33.4|:443... connected.  
HTTP request sent, awaiting response... 200 OK  
Length: 719323136 (686M) [application/octet-stream]  
Saving to: 'CentOS-7-livecd-x86_64.iso'  
  
CentOS-7-livecd-x86_64.iso                           100%[======================================================================================================================>] 686.00M   554KB/s    in 21m 58s   
  
2020-02-04 06:12:19 (533 KB/s) - 'CentOS-7-livecd-x86_64.iso' saved [719323136/719323136]  
  
$ free  
             total       used       free     shared    buffers     cached  
Mem:      64463556    4903112   59560444         68      82844    4435296  
-/+ buffers/cache:     384972   64078584  
Swap:      4194300        768    4193532  

-> ちょっと swap 領域もあるためわかりにくいが、ファイルキャッシュとして利用された領域は一気に少なくなることがわかる。


 © 2023, Dealing with Ambiguity