在centos7的/sys/fs/cgroup下面能夠看到與cpu相關的有cpu,cpuacct和cpuset 3個subsystem。cpu用於對cpu使用率的劃分;cpuset用於設置cpu的親和性等,主要用於numa架構的os;cpuacct記錄了cpu的部分信息。對cpu資源的設置能夠從2個維度考察:cpu使用百分比和cpu核數目。前者使用cpu subsystem進行配置,後者使用cpuset subsystem進程配置。首先看cpu subsystem的用法html
cpu subsystemnode
cgroup使用以下2種方式來對cpu進行調度mysql
cpu subsystem主要涉及5接口:cpu.cfs_period_us,cpu.cfs_quota_us,cpu.shares,cpu.rt_period_us,cpu.rt_runtime_uslinux
cpu.cfs_period_us用於設置cpu時間週期長度,單位爲微秒us。cpu.cfs_quota_us設置cpu.cfs_period_us週期內cgroup可運行的cpu的總時間,多核場景下,如配置cpu.cfs_period_us=10000,而cpu.cfs_period_us=20000,表示該cgroup能夠徹底使用2個cpu。git
首先在/sys/fs/cgroup/cpu下面新建一個cgroup,將cpu週期設置爲100000,cgroup在單個週期中佔用時長爲50000,即單個cpu的50%github
# cat cpu.cfs_period_us 100000 # echo 50000 > cpu.cfs_quota_us # bash # cat tasks # echo $$ 40768 # echo $$ > cgroup.procs # while true; do a=a+1;done
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 40768 root 20 0 116872 3644 1808 R 50.3 0.4 0:19.75 bash
下例中將cpu週期設置爲100000,cgroup在單個週期中佔用時長爲300000,即該cgroup能夠徹底佔用3個cpu(當前環境4 cpu)。sql
啓動一個bash執行while true; do a=a+1;done並將該進程加入到cgroup.procs,使用top命令能夠看到1個cpu使用率已經達到100%docker
top - 13:20:06 up 19:24, 7 users, load average: 3.21, 2.03, 0.95 Tasks: 252 total, 3 running, 249 sleeping, 0 stopped, 0 zombie %Cpu0 : 0.3 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 995896 total, 75412 free, 547276 used, 373208 buff/cache KiB Swap: 2097148 total, 1651216 free, 445932 used. 138856 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 41416 root 20 0 116872 3644 1808 R 99.7 0.4 5:41.19 bash
(新shell中)再啓動一個bash執行while true; do a=a+1;done,將該進程加入到cgroup.procs,使用top命令能夠看到2個cpu使用率已經達到100%shell
top - 13:22:51 up 19:27, 7 users, load average: 1.42, 1.65, 0.98 Tasks: 252 total, 3 running, 249 sleeping, 0 stopped, 0 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.3 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 995896 total, 75124 free, 547544 used, 373228 buff/cache KiB Swap: 2097148 total, 1651216 free, 445932 used. 138252 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 41416 root 20 0 116872 3644 1808 R 100.0 0.4 8:26.67 bash 41528 root 20 0 116872 3652 1808 R 100.0 0.4 4:22.60 bash
(新shell中)再啓動一個bash執行while true; do a=a+1;done,將該進程加入到cgroup.procs,使用top命令能夠看到3個cpu使用率已經達到100%數據庫
top - 13:25:58 up 19:30, 7 users, load average: 2.28, 1.88, 1.18 Tasks: 251 total, 4 running, 247 sleeping, 0 stopped, 0 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 995896 total, 75412 free, 547584 used, 372900 buff/cache KiB Swap: 2097148 total, 1651216 free, 445932 used. 138228 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 41528 root 20 0 116872 3652 1808 R 100.0 0.4 7:29.10 bash 41416 root 20 0 116872 3644 1808 R 99.7 0.4 11:33.12 bash 41593 root 20 0 116784 3368 1648 R 99.7 0.3 2:30.04 bash
(新shell中)再啓動一個bash執行while true; do a=a+1;done,將該進程加入到cgroup.procs,此時有4個進程同時消耗cpu,但整體消耗限制在3個cpu,以下圖中,每一個bash消耗的cpu約75%
top - 13:26:49 up 19:31, 7 users, load average: 2.95, 2.12, 1.30 Tasks: 251 total, 5 running, 246 sleeping, 0 stopped, 0 zombie %Cpu0 : 74.8 us, 0.0 sy, 0.0 ni, 25.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 74.8 us, 0.0 sy, 0.0 ni, 25.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 74.2 us, 0.0 sy, 0.0 ni, 25.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 75.7 us, 0.0 sy, 0.0 ni, 24.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 995896 total, 75536 free, 547460 used, 372900 buff/cache KiB Swap: 2097148 total, 1651216 free, 445932 used. 138352 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 41593 root 20 0 116784 3368 1648 R 75.7 0.3 3:16.76 bash 41528 root 20 0 116872 3652 1808 R 74.8 0.4 8:15.67 bash 41416 root 20 0 116872 3644 1808 R 74.1 0.4 12:19.74 bash 41654 root 20 0 116784 3368 1648 R 74.1 0.3 1:41.05 bash
cpu.cfs_quota_us和cpu.cfs_period_us以絕對比例限制cgroup的cpu,而cpu.shares以相對比例限制cgroup的cpu。
在/sys/fs/cgroup/cpu/下建立2個cgroup:test1和test2,設置test1的cpu.shares=50,test2的cpu.shares=200,則意味着test1在cpu競爭下最多可使用全部cpu的20%,而test2在cpu競爭下最多可使用全部cpu的80%(不考慮系統基本進程佔用)。爲方便驗證,將系統的cpu設置爲1個。建立2個bash進程分別加入2個cgroup後執行while true; do a=a+1;done
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 9683 root 20 0 116872 3644 1808 R 80.0 0.4 0:16.77 bash 9629 root 20 0 116872 3644 1808 R 20.0 0.4 0:09.73 bash
使用cpu.shares須要注意的是,對cpu的相對比例是在cpu競爭的條件下,若是一個cgroup使用的相對比例是50%,但實際僅使用了10%,那麼多餘的cpu會被回收,給其餘cgroup使用,參見CPU
當一個 cgroup 中的任務處於閒置狀態且不使用任何 CPU 時間時,剩餘的時間會被收集到未使用的 CPU 循環全局池中。其它 cgroup 能夠從這個池中借用 CPU 循環
下例中test1 cgroup設定50,test2 cgroup設定200,但test1中運行的進程很是消耗cpu,而test2中運行的進程僅使用很小一部分cpu,且sleep操做會致使其進程進入sleep狀態
Test1 cgroup # echo $$ 9629 [root@ test1]# cat cpu.shares 50 [root@ test1]# while true; do a=a+1;done Test2 cgroup # echo $$ 9683 [root@ test2]# cat cpu.shares 200 [root@ test2]# while true; do sleep 1 ;done
查看cpu佔用,能夠看到test1中的進程佔用了99.3%的cpu,而其相對比例爲20%
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 9629 root 20 0 116872 3660 1808 R 99.3 0.4 9:32.48 bash
cpuset subsystem
cpuset主要是爲了NUMA(非均勻訪問存儲模型)使用的,NUMA技術將CPU劃分紅不一樣的組(Node),每一個Node由多個CPU組成,而且有獨立的本地內存、I/O等資源(硬件上保證)。可使用numactl查看當前系統的node清空,以下面表示系統只有一個node,含cpu 0-3,內存大小約1G
# numactl -H available: 1 nodes (0) node 0 cpus: 0 1 2 3 node 0 size: 1023 MB node 0 free: 70 MB node distances: node 0 0: 10
可使用dmesg | grep -i numa命令查看當前系統是否開啓了numa下·
numa的基本架構以下,當cpu訪問直接attach的內存時(local access)時會有較大效率,而訪問其餘cpu attach的內存(remote access)會致使效率降低。
Numa內存分配策略有一下四種,通常採用默認方式
numa場景下可能會出現一個性能問題,NUMA架構的CPU,The MySQL 「swap insanity」 problem and the effects of the NUMA architecture和A brief update on NUMA and MySQL。發生性能的主要緣由是由於more策略下可能會發生swap,即老是在本地節點分配內存,當本地內存不足時會發生swap,能夠嘗試使用以下方式進行
默認方式下,進程老是使用本地節點進程內存分配,可使用numastat查看內存分配狀況
# numastat node0 numa_hit 6711656 numa_miss 0 numa_foreign 0 interleave_hit 19532 local_node 6711656 other_node 0
cpuset調用sched_setaffinity來設置進程的cpu親和性,調用mbind和set_mempolicy來設置內存的親和性。能夠經過查看/proc/$pid/status查看當前進程cpu和mem的親和性。cpuset使用中應該遵循如下3點
以下例中,在/sys/fs/cgroup/cpuset中建立2個cgroup,按照以下步驟,能夠看出,當test1和test2有重合時,設置cpuset失敗
# rmdir test1 [root@ cpuset]# mkdir test1 [root@ cpuset]# mkdir test2 [root@ cpuset]# echo 1 > test1/cpuset.cpu_exclusive [root@ cpuset]# echo 1 > test2/cpuset.cpu_exclusive [root@ cpuset]# echo 0,1 > test1/cpuset.cpus [root@ cpuset]# echo 1,2 > test2/cpuset.cpus -bash: echo: write error: Invalid argument [root@ cpuset]# echo 2 > test2/cpuset.cpus
cpuset.cpu_exclusive:包含標籤(0
或者 1
),它能夠指定:其它 cpuset 及其父、子 cpuset 是否可共享該 cpuset 的特定 CPU。默認狀況下(0
),CPU 不會專門分配給某個 cpuset 。
上面介紹了設置該標誌後兄弟cpuset之間的cpuset.cpus不能有重合,但父子cpuset之間是必須重合的。cpu_exclusive標記並不能實現徹底的cpu隔離(不隸屬於cgroup管轄的進程默認擁有全部的cpu權限),以下例中啓動了6個消耗cpu的bash進程,僅對其中一個bash進程進行了cpuset的exclusive,能夠看到exclusive並不能保證cpu的隔離,只用於保證不於其餘兄弟cpuset定義的cpus重疊。核隔離可使用內核啓動參數isolcpus,隔離的cpu不會對其進行負載均衡操做。
Tasks: 243 total, 7 running, 236 sleeping, 0 stopped, 0 zombie %Cpu0 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 995896 total, 68208 free, 654032 used, 273656 buff/cache KiB Swap: 2097148 total, 1928188 free, 168960 used. 92388 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 74809 root 20 0 116652 3300 1656 R 86.0 0.3 1:27.86 bash 74753 root 20 0 116652 3300 1656 R 66.4 0.3 1:57.41 bash 74890 root 20 0 116652 3304 1656 R 66.4 0.3 0:11.07 bash 74081 root 20 0 116740 3572 1808 R 66.1 0.4 3:23.12 bash 70206 root 20 0 116784 3120 1376 R 62.5 0.3 1:38.89 bash 72544 root 20 0 116784 3556 1800 R 52.2 0.4 1:57.57 bash
cpuset.memory_spread_page用於設定文件系統緩衝是否應在該 cpuset 的內存節點中均勻分佈,cpuset.memory_spread_slab用於設定slab緩衝(如inode和dentries)是否應在該 cpuset 的內存節點中均勻分佈,默認否。該策略在將(大的)數據文件分佈到多個node時能夠提高性能(平均分佈)。
cpuset.sched_load_balance和cpuset.sched_relax_domain_level與cpu負載均衡有關。linux使用sched domains(調度域)爲單位進行負載均衡。當sched_load_balance設置爲enable時,會在該cpuset中的cpu上進行負載均衡,不然不會在該cpuset中的cpu上進行負載均衡(不一樣cpuset中重疊的cpu上可能也會有負載均衡)。當root cpuset的sched_load_balance爲enable時,會在全部的cpu上進行負載均衡,此時會忽略全部子cpuset中對該值的設置,所以只有在root cpuset disable以後,子cpuset才能生效。cpu負載均衡會影響系統性能,在如下兩種狀況下能夠不須要該功能:
cpuset.sched_relax_domain_level表示 kernel 應嘗試平衡負載的 CPU 寬度範圍,僅當cpuset.sched_load_balance enable時生效。通常無需改動。
cpuset.memory_migrate包含一個標籤(0
或者 1
),用來指定當 cpuset.mems
的值更改時,是否應該將內存中的頁遷移到新節點。
總結:
使用cpu subsystem能夠在cpu時間上限制進程,而使用cpuset能夠在cpu/mem number上限制進程。但若是cpu和cpuset不匹配時應該如何處理?以下例中,在cpuset中限制該cgroup中的進程只能運行在2號核上,但在cpu中該cgroup的進程最多可使用2個核
# mkdir cpuset/cpusettest # mkdir cpu/cputest # cd cpuset/cpusettest # echo 0 > cpuset.mems # echo 2 > cpuset.cpus # cd cpu/cputest # echo 1000 > cpu.cfs_period_us # echo 2000 > cpu.cfs_quota_us
啓動3個bash執行while true; do a=a+1;done,並將其pid加入到cpu和cpuset的cgroup.procs中,觀察top命令能夠看到3個bash進程僅佔用了2號核,每一個cpu佔用率都約等於33%。由此可知,cpu中規定了進程可使用的cpu的上限,但並不必定能達到上限
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 995896 total, 68408 free, 647088 used, 280400 buff/cache KiB Swap: 2097148 total, 1928444 free, 168704 used. 92768 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 72544 root 20 0 116784 3556 1800 R 33.9 0.4 4:19.03 bash 70206 root 20 0 116784 3120 1376 R 33.2 0.3 3:58.17 bash 74753 root 20 0 116652 3300 1656 R 33.2 0.3 5:05.08 bash
TIPS:
參考:
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/resource_management_guide/sec-cpu
https://segmentfault.com/a/1190000008323952
http://cenalulu.github.io/linux/numa/
https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt