Nginx采用多进程Master/Worker结构,Worker进程数为CPU个数时工作效率最高,Nginx通过affinity为每个Worker进程绑定一个CPU,避免进程切换带来的消耗,同时能够保证缓存命中率。
Nginx配置文件conf/nginx.conf中关于Worker进程个数,和affinity的配置命令:
worker_processes 4; worker_cpu_affinity 1000 0100 0010 0001;
应用程序可以主动调用接口设定:
Linux进程:
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 #define _GNU_SOURCE 2 3 #include <sched.h> 4 #include <unistd.h> 5 6 void do_something(void); 7 8 int 9 main(void) 10 { 11 pid_t pid; 12 cpu_set_t mask; 13 14 if((pid = fork()) == 0){ 15 do_something(); 16 } 17 CPU_ZERO(&mask); 18 CPU_SET(0,&mask); 19 sched_setaffinity(pid,sizeof(cpu_set_t),&mask); 20 21 if((pid = fork()) == 0){ 22 do_something(); 23 } 24 CPU_ZERO(&mask); 25 CPU_SET(1,&mask); 26 sched_setaffinity(pid,sizeof(cpu_set_t),&mask); 27 28 wait(); 29 wait(); 30 } 31 32 void 33 do_something(void) 34 { 35 int i; 36 while(1){ 37 i = 1; 38 } 39 }
FreeBSD上可以通过调用cpuset_setaffinity设定
Nginx源码src/os/unix/nginx_setaffinity.c中实现对Linux和FreeBSD中设置亲和性的包装,根据配置文件设置Worker进程亲和性
当然,POSIX线程也可以设置亲和性:
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);
已经运行的进程也可以通过外部命令设定:
taskset [options] mask command [arg]...
taskset [options] -p [mask] pid