FreeBSD自7.1以后,就可以使用cpuset来绑定CPU,即可以把某个进程或线程运行于指定的CPU上面。绑定CPU带的有明显好处主要是减少CPU上下文的切换和提高缓存命中率,在繁忙的系统上可以带来一定的好处。
其实这个功能在windows xp和Linux上面已经存在了很长时间,FreeBSD在这方面稍微有点落后。
大致原理跟Linux中差不多,可以创建多个集合,叫cpuset,每个集合里包含多个CPU,当然可以仅有一个,然后把某个程序跟这个集合联系起来就可以了。
系统有个默认的cpuset,id号为1,是所有程序的默认cpu集,如果程序没有指定cpuset,则默认为cpuset 1。cpuset 1中它默认包含所有系统中的cpu,当然可以更改。
实际应用中,可以不指定cpuset。(注:在大多数情况下,系统会自动创建一个cpuset,但有时用cpuset -g命令查不到创建的cpuset,这难道是系统的一个bug?)
先来看官方的例子:开启一个shell,绑定在cpu0,cpu1上:
# cpuset -l 0,1 /bin/sh
这个命令直接绑定CPU,是最常用的命令。 -l后面跟cpu代号的列表,用逗号分隔,也可以用“-”来表示范围,比如:-l 3-8,表示用第四个cpu到第九个cpu。再后面直接跟要运行的命令,运行命令的参数直接放命令后面。
需要提醒的是:可以用这个命令开启服务,比如把mysql限制在cpu4-7中,可以用命令:
# cpuset -l 4-7 /usr/local/etc/rc.d/mysql-server forcestart
可以用top来验证,其中倒数第四列就是cpu代号,下面的示例为零:
455 root 1 20 0 16988K 2688K ttyin 0 0:00 0.00% sh
需要注意的是,这种绑定有继承性,也就是sh绑定为cpu0和1,则此sh中启动的所有进程都继承了这个绑定,比如在这个sh中启动一个比较耗时的查找操作:
find / -name “*”
然后再看top,可以看到find仍然使用了cpu0:
PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND
480 root 1 21 0 12300K 1960K ttyout 0 0:00 1.32% find
怎么样查看一个程序是不是绑定了CPU呢?首先要知道pid才行,在top中就能查到,第一列就是pid号,sh对应的是455:
# cpuset -g -p 455
pid 455 mask: 0, 1
从上面的结果可以看到,sh用的是0和1。
再看系统默认的cpuset,服务器cpu,有12个核:
% cpuset -g -s 1
cpuset 1 mask: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
还有一种情况,怎么样对已运行的进程绑定CPU呢?这个也简单,直接操作pid就可以了,比如已经运行的nginx:
99644 www 1 20 0 23936K 5084K kqread 22 0:27 0.00% nginx
可以用命令:
# cpuset -l 8 -p 99644
cpuset还可以绑定线程,比如mysql就是一个多线程的程序。要先取得线程号,可以用ps取得:
% ps -aHxo lwp,comm | grep mysql
100147 mysqld/mysqld
100316 mysqld/mysqld
100317 mysqld/mysqld
100318 mysqld/mysqld
……
把线程号100147绑定在第四个cpu,用参数-t 来指定线程号:
# cpuset -l 3 -t 100147
cpuset还可以绑定中断号,比如用来绑定raid卡mfi为第五块cpu,用参数-x来指定,但是先用vmstat -i来查看各设备的中断号:
# vmstat -i
interrupt total rate
irq16: ehci0 20910020 1
irq23: ehci1 42700118 3
cpu0:timer 25871006504 2004
irq264: mfi0 19441951 1
…..
# cpuset -l 4 -x 264
提醒:千万别对网卡绑定到单一的cpu,最新的网卡都是对smp优化过的,多cpu才能发挥它的作用。
最后一个应用,怎么样修改默认的cpuset?这样才可以把某些cpu彻底空闲出来,用作专门用途。
示例:默认cpuset为cpu0和cpu1:
# cpuset -l 0,1 -s 1
该贴由hui.chen转至本版2014-11-27 18:24:24