changeset 6335:96c4297375bc

Core: worker_cpu_affinity auto. If enabled, workers are bound to available CPUs, each worker to once CPU in order. If there are more workers than available CPUs, remaining are bound in a loop, starting again from the first available CPU. The optional mask parameter defines which CPUs are available for automatic binding. In collaboration with Vladimir Homutov.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 11 Jan 2016 19:23:17 +0300
parents b31928ca3870
children 02abce4764b7
files src/core/nginx.c src/core/ngx_cycle.h
diffstat 2 files changed, 42 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -961,6 +961,7 @@ ngx_core_module_create_conf(ngx_cycle_t 
      *     ccf->pid = NULL;
      *     ccf->oldpid = NULL;
      *     ccf->priority = 0;
+     *     ccf->cpu_affinity_auto = 0;
      *     ccf->cpu_affinity_n = 0;
      *     ccf->cpu_affinity = NULL;
      */
@@ -1002,7 +1003,8 @@ ngx_core_module_init_conf(ngx_cycle_t *c
 
 #if (NGX_HAVE_CPU_AFFINITY)
 
-    if (ccf->cpu_affinity_n
+    if (!ccf->cpu_affinity_auto
+        && ccf->cpu_affinity_n
         && ccf->cpu_affinity_n != 1
         && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
     {
@@ -1273,7 +1275,24 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx
 
     value = cf->args->elts;
 
-    for (n = 1; n < cf->args->nelts; n++) {
+    if (ngx_strcmp(value[1].data, "auto") == 0) {
+
+        if (cf->args->nelts > 3) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid number of arguments in "
+                               "\"worker_cpu_affinity\" directive");
+            return NGX_CONF_ERROR;
+        }
+
+        ccf->cpu_affinity_auto = 1;
+        mask[0] = (uint64_t) -1 >> (64 - ngx_min(64, ngx_ncpu));
+        n = 2;
+
+    } else {
+        n = 1;
+    }
+
+    for ( /* void */ ; n < cf->args->nelts; n++) {
 
         if (value[n].len > 64) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1323,6 +1342,8 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx
 uint64_t
 ngx_get_cpu_affinity(ngx_uint_t n)
 {
+    uint64_t          mask;
+    ngx_uint_t        i;
     ngx_core_conf_t  *ccf;
 
     ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
@@ -1332,6 +1353,24 @@ ngx_get_cpu_affinity(ngx_uint_t n)
         return 0;
     }
 
+    if (ccf->cpu_affinity_auto) {
+        mask = ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
+
+        if (mask == 0) {
+            return 0;
+        }
+
+        for (i = 0; /* void */ ; i++) {
+            if ((mask & ((uint64_t) 1 << (i % 64))) && n-- == 0) {
+                break;
+            }
+
+            /* void */
+        }
+
+        return (uint64_t) 1 << (i % 64);
+    }
+
     if (ccf->cpu_affinity_n > n) {
         return ccf->cpu_affinity[n];
     }
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -88,6 +88,7 @@ typedef struct {
 
      int                      priority;
 
+     ngx_uint_t               cpu_affinity_auto;
      ngx_uint_t               cpu_affinity_n;
      uint64_t                *cpu_affinity;