一,背景

在服务器压力特别大,心跳经常丢失从而造成服务超时。经过分析发现网络没有问题,心跳网络包都发过来了而且也正常进入了dispatch队列,但是由于dispatch在处理别的request的时候耗时过长,而且要命的是它还hold着一把全局的锁,导致队列里面的其他queue也无法正常被dispatch。所以我们想到可以利用设置CPU亲和性来保证核心进程/线程得到足够的时间片,从而不让服务超时。

二,CPU隔离

说到亲和性,如果我们不隔离CPU,那么就只能减少CPU切换,提高cpu cache的命中率,从而减少内存访问损耗,提高程序的速度。但是这样做只能保证自己不被调度到的别的CPU,却不能阻止其他线程不来我这个CPU。这样就成了“我的是公共的,别人的我不能用!”,岂不是我得到的时间片更少了?所以为了防止这样的窘境,我们还得先“隔核”再“绑核”。

隔离CPU核心

我们可以用如下命令来查看自己的服务器有多少个核心:

[root@xt1 ~]# cat /proc/cpuinfo |grep "model name"

model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz

model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz

model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz

model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz

model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz

model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz

隔核方法: 修改grub

环境: CentOS7

具体步骤: (隔离4,5核心)

找到内核启动项,在其后面添加 “isolcpus=4,5”

linux16 /boot/vmlinuz-3.10.0-514.26.2.el7.x86_64 root=UUID=8c3205a6-2433-4799-8413-c74e4fe97f5c ro crashkernel=auto rhgb quiet LANG=en_US.UTF-8 systemd.debug isolcpus=4,5

reboot 重启服务器

检查启动项是否设置成功

[root@xt1 ~]# cat /proc/cmdline

BOOT_IMAGE=/boot/vmlinuz-3.10.0-514.26.2.el7.x86_64 root=UUID=8c3205a6-2433-4799-8413-c74e4fe97f5c ro crashkernel=auto rhgb quiet LANG=en_US.UTF-8 systemd.debug isolcpus=4,5

检查隔离是否生效

// 如果设置成功,则落在该核心的线程会很少

ps -eLo pid,user,lwp,psr | awk '{if($4==4) print $0}' //检查核心4

ps -eLo pid,user,lwp,psr | awk '{if($4==5) print $0}' //检查核心5

// 也可以用top命令来查看

执行top,按数字1,就可以调出每个核心的使用状态,然后按下f按键,向下找到"P= Last Used Cpu (SMP)"这一行,按下回车,再按q按键返回,就可以看到每个线程具体落在哪个核心上面

top - 16:28:40 up 5 days, 22:03, 2 users, load average: 0.02, 0.08, 0.44

Tasks: 260 total, 2 running, 258 sleeping, 0 stopped, 0 zombie

%Cpu0 : 0.0 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st

%Cpu1 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.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

%Cpu4 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

%Cpu5 : 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 : 7840224 total, 738160 free, 506176 used, 6595888 buff/cache

KiB Swap: 9727996 total, 9250224 free, 477772 used. 6992616 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND P

2894 root 20 0 51192 18928 2884 S 1.0 0.2 74:29.74 etcd 1

2836 root 20 0 1855044 50728 3296 S 0.7 0.6 25:13.31 ceph-osd 3

4648 root 20 0 146304 2200 1436 R 0.7 0.0 0:00.10 top 1

1813 root 20 0 554324 64492 9676 S 0.3 0.8 0:12.40 ceph-mds 1

3041 root 20 0 0 0 0 S 0.3 0.0 4:10.88 xfsaild/dm-8 1

3120 root 20 0 1818688 97464 2580 S 0.3 1.2 24:13.09 ceph-osd 2

30405 root 20 0 0 0 0 S 0.3 0.0 0:01.33 kworker/0:2 0

1 root 20 0 43476 2472 1340 S 0.0 0.0 0:30.26 systemd 3

三,sched_setaffinity/sched_getaffinity

更改一个进程的CPU affinity mask,可以设置一个进程在某个CPU核心上执行,也可以设置该进程在除了某CPU 核心之外的其他CPU核心上执行。如果第一个参数pid为0,则设置当前进程的mask。

其实这个mask是一个针对线程组内的线程属性,可以被独立调节。所以我们可以用gettid()的参数作为第一个参数,同样如果第一个参数为0,则设置当前线程。如果传的getpid的返回值,则设置该线程组的主线程mask属性。

int sched_setaffinity(pid_t pid, size_t cpusetsize,

cpu_set_t *mask);

int sched_getaffinity(pid_t pid, size_t cpusetsize,

cpu_set_t *mask);

实验1

#include

#define __USE_GNU

#include

#include

#include

#include

void * fn(void *arg)

{

cpu_set_t set;

int i = 0;

CPU_ZERO(&set);

CPU_SET(1, &set);

printf("child thread is arriving .../n");

sched_setaffinity(0, sizeof(cpu_set_t), &set);

while (i<100000000)

{

i++;

if (i%5000 == 0)

{

printf ("i is %d\n", i);

sleep(1);

}

}

}

int main()

{

int isolated = 1;

pthread_t tid;

pthread_create(&tid, NULL, fn, NULL);

pthread_join(tid, NULL);

return 0;

}

四,pthread_setaffinity_np/pthread_getaffinity_np

更改一个线程的CPU affinity mask, 同样也是可以设置一个线程在某个CPU核心上执行,也可以设置该线程在除了某CPU 核心之外的其他CPU核心上执行。这两个接口在底层也是调用sched_setaffinity/sched_getaffinity。当第一个参数为0时,就是设置当前thread的mask。

#define _GNU_SOURCE /* See feature_test_macros(7) */

#include

int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,

const cpu_set_t *cpuset);

int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize,

cpu_set_t *cpuset);

Compile and link with -pthread.

实验2

#include

#define __USE_GNU

#include

#include

#include

#include

void self_sleep()

{

int i = 0;

while (i<100000000)

{

i++;

if (i%5000 == 0)

{

printf ("i is %d\n", i);

sleep(1);

}

}

}

void * fn(void *arg)

{

cpu_set_t set;

pthread_attr_t tattr;

pthread_attr_init(&tattr);

CPU_ZERO(&set);

CPU_SET(1, &set);

printf("child thread is arriving .../n");

pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &set);

self_sleep();

}

int main()

{

int isolated = 1;

pthread_t tid;

pthread_create(&tid, NULL, fn, NULL);

pthread_join(tid, NULL);

return 0;

}

五,属性继承

上面我们介绍了两种设置CPU affinity mask的接口,但是无论是哪一种接口有个共同的特性:创建出来的子线程默认会继承父亲线程的CPU affinity mask。在复杂的系统中有时并不希望这个属性的出现,因为可能会导致某个隔离出来的cpu上还是运行了很多的thread。所以我就想了一个解决方案来解决这个问题。

让所有的线程创建出来之后都跑在除了隔离出来的核心之外的其他核心上面,然后在单独为需要绑定核心的线程来设置CPU affinity mask

实验3

#include

#define __USE_GNU

#include

#include

#include

#include

void self_sleep()

{

int i = 0;

while (i<100000000)

{

i++;

if (i%5000 == 0)

{

printf ("i is %d\n", i);

sleep(1);

}

}

}

void * fn2(void *arg)

{

printf("child2 thread is arriving .../n");

self_sleep();

}

void * fn(void *arg)

{

int i, cpus;

cpu_set_t set;

pthread_t tid;

pthread_attr_t tattr;

pthread_attr_init(&tattr);

cpus = sysconf(_SC_NPROCESSORS_CONF);

printf("have %d cpus\n", cpus);

CPU_ZERO(&set);

for (i=0; i

{

if (i == 1)

continue;

CPU_SET(i, &set);

}

printf("child thread is arriving .../n");

printf("set child thread cpu to 0 .../n");

pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &set);

pthread_create(&tid, NULL, fn2, NULL);

self_sleep();

pthread_join(tid, NULL);

}

int main()

{

int isolated = 1;

cpu_set_t set;

CPU_ZERO(&set);

CPU_SET(1, &set);

pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &set);

pthread_t tid;

pthread_create(&tid, NULL, fn, NULL);

pthread_join(tid, NULL);

return 0;

}

参考文档

linux affinity,Linux CPU Affinity相关推荐

  1. Linux CPU affinity

    在Linux中,我们知道可以通过nice.renice命令改变进程的执行优先级,优先级高的进程优先执行,从而一定程度上保证重要任务的运行. 除了nice.renice外,可以通过CPU  affini ...

  2. linux 线程与CPU绑定

    看到很多程序都是根据CPU个数来创建线程个数,当时很不理解他们之间的关系,请教了项目组的同事后才有了大致了解.  1. 相关系统函数 下面的函数可以通过man命令查询到. SYNOPSIS#defin ...

  3. taskset设置CPU affinity

    Retrieve or set a processes's CPU affinity(亲和). This requires sched_{g,s}etaffinity support in your ...

  4. 线程锁定CPU linux,linux 线程与CPU绑定

    看到很多程序都是根据CPU个数来创建线程个数,当时很不理解他们之间的关系,请教了项目组的同事后才有了大致了解. 1. 相关系统函数 下面的函数可以通过man命令查询到. SYNOPSIS #defin ...

  5. linux 指定cpu运行线程,linux 线程与CPU绑定

    看到很多程序都是根据CPU个数来创建线程个数,当时很不理解他们之间的关系,请教了项目组的同事后才有了大致了解. 1. 相关系统函数 下面的函数可以通过man命令查询到.SYNOPSIS #define ...

  6. 【Linux系统编程】| Linux性能优化——CPU亲缘性

    文章目录 一.CPU亲和性 1.1 使用场景 二.使用接口 测试 一.CPU亲和性 CPU亲和性又称CPU关联,可以映射到一个或多个CPU上.该技术基于对称多处理机操作系统中的native centr ...

  7. Linux下操纵CPU曲线绘制心形

    不久之前看了「编程之美」,里面有在windows下操纵CPU绘制正弦曲线的示例程序.思路很简单,但是需要知道几个windows的API函数. 刚开始我想尝试在windows下绘制心形,不过没能做到,原 ...

  8. linux c设置cpu亲和力,关于多线程:如何设置特定pthread的CPU亲和力?

    我想指定特定pthread的cpu亲和力. 到目前为止,我发现的所有引用都涉及设置进程(pid_t)而不是线程(pthread_t)的cpu亲和力. 我尝试了一些传递pthread_t的实验,并且按预 ...

  9. Linux设置进程CPU亲和力(核心绑定)

    文章目录 1. 获取CPU核数 2. 线程绑定CPU核心 ① 概念 ② 函数 ③ 例子 1. 获取CPU核数 int CPU_NUM = sysconf(_SC_NPROCESSORS_CONF); ...

  10. Unix/Linux编程:CPU亲和力

    CPU亲和力 当一个进程在一个多处理器系统上被重新调度时无需在上一次执行的CPU上运行.之所以会在另一个CPU上运行的原因是原来的CPU处于忙碌状态. 进程切换CPU时对性能会有一定的影响:如果在原来 ...

最新文章

  1. linux 列出内存/cpu使用率前10的进程
  2. tomcat使用说明
  3. 中国大学MOOC 人工智能导论第四章测试
  4. 命令行分析java线程CPU占用
  5. (转) 基于MapReduce的ItemBase推荐算法的共现矩阵实现(一)
  6. 诗与远方:无题(七十一)- 雨季来了
  7. 混音教程入门|新手学混音必须注意这9点!| MZD Studios
  8. css实现渐变色遮罩层(模糊毛边)
  9. 应用商店-华为应用市场
  10. php控制舵机,分享一个关于SG90舵机的实验(+串口控制)
  11. 名字空间的含义及作用
  12. 阿里云服务器的公网ipv6地址申请与配置
  13. linux物理内存没用完swap占用大,Linux占用swap分区过高,物理内存还有剩余
  14. 踩坑记-- UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xa6 in position 17: illegal multibyte seque
  15. halcon机器视觉之玩转车牌识别-超人视觉罗超
  16. 常见的挖矿程序处理方式
  17. 苹果浏览器显示打不开改网页无法连接服务器,为什么苹果浏览器老是显示safari打不开该网页答案...
  18. python的歌曲评论数据分析_用Python爬取陈奕迅歌曲10万条评论的新发现
  19. sawtooth,井字棋演示和交易族开发流程介绍
  20. 每日新闻 | Google AI 负责人Jeff Dean:机器学习让计算机更智能

热门文章

  1. php-fpm master 关系,php-fpm master worker 关系介绍
  2. 两步完成druid数据库连接池的密文配置
  3. 打印机驱动无法安装到计算机是,解决方法:Win7无法安装打印机,也找不到核心驱动程序包。...
  4. 关于在word中安装Mathtype
  5. windows cmd 批处理将文件名改为大写:https://blog.csdn.net/llq108/article/details/47185279
  6. 【题解】Luogu P3110 [USACO14DEC]驮运Piggy Back
  7. 转载---英语 是否 双写 规则
  8. schedule_timeout 函数分析
  9. linux dropbox自动同步,Linux免dropbox客户端备份脚本
  10. python大众点评霸王餐_如何抽中大众点评霸王餐?