From 5f52063b9ea5d8d54eb3712e5b29eaed006dca6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Sun, 29 Sep 2013 20:30:29 +0200 Subject: [PATCH] cheaper API change to allow signaling cheaper algo if it can spawn new workers or only cheap them. Fixes #394 --- core/master_utils.c | 20 +++++++++++------ plugins/cheaper_busyness/cheaper_busyness.c | 24 ++++++++++----------- uwsgi.h | 14 ++++++------ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/core/master_utils.c b/core/master_utils.c index 427de9c3..2b3342ea 100644 --- a/core/master_utils.c +++ b/core/master_utils.c @@ -151,7 +151,13 @@ int uwsgi_calc_cheaper(void) { uwsgi.cheaper_fifo_delta = 0; } - if (!ignore_algo) needed_workers = uwsgi.cheaper_algo(); + // if cheaper limits wants to change worker count, then skip cheaper algo + if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo); + // safe check to verify if cheaper algo obeyed ignore_algo value + if (ignore_algo && needed_workers > 0) { + uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers); + needed_workers = 0; + } if (needed_workers > 0) { for (i = 1; i <= uwsgi.numproc; i++) { @@ -189,7 +195,7 @@ int uwsgi_calc_cheaper(void) { } // fake algo to allow control with the fifo -int uwsgi_cheaper_algo_manual(void) { +int uwsgi_cheaper_algo_manual(int can_spawn) { return 0; } @@ -228,7 +234,7 @@ int uwsgi_cheaper_algo_manual(void) { */ -int uwsgi_cheaper_algo_spare(void) { +int uwsgi_cheaper_algo_spare(int can_spawn) { int i; static uint64_t overload_count = 0; @@ -252,7 +258,7 @@ int uwsgi_cheaper_algo_spare(void) { healthy: // are we overloaded ? - if (overload_count > uwsgi.cheaper_overload) { + if (can_spawn && overload_count > uwsgi.cheaper_overload) { #ifdef UWSGI_DEBUG uwsgi_log("overloaded !!!\n"); @@ -320,7 +326,7 @@ healthy: */ -int uwsgi_cheaper_algo_backlog(void) { +int uwsgi_cheaper_algo_backlog(int can_spawn) { int i; #ifdef __linux__ @@ -329,7 +335,7 @@ int uwsgi_cheaper_algo_backlog(void) { int backlog = 0; #endif - if (backlog > (int) uwsgi.cheaper_overload) { + if (can_spawn && backlog > (int) uwsgi.cheaper_overload) { // activate the first available worker (taking step into account) int decheaped = 0; // search for cheaped workers @@ -1345,7 +1351,7 @@ end: return NULL; } -void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) { +void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) { struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos; diff --git a/plugins/cheaper_busyness/cheaper_busyness.c b/plugins/cheaper_busyness/cheaper_busyness.c index 29b98b34..934e4c9a 100644 --- a/plugins/cheaper_busyness/cheaper_busyness.c +++ b/plugins/cheaper_busyness/cheaper_busyness.c @@ -142,7 +142,7 @@ int spawn_emergency_worker(int backlog) { #endif -int cheaper_busyness_algo(void) { +int cheaper_busyness_algo(int can_spawn) { int i; // we use microseconds @@ -243,11 +243,12 @@ int cheaper_busyness_algo(void) { uwsgi_cheaper_busyness_global.tolerance_counter = 0; int decheaped = 0; - for (i = 1; i <= uwsgi.numproc; i++) { - - if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) { - decheaped++; - if (decheaped >= uwsgi.cheaper_step) break; + if (can_spawn) { + for (i = 1; i <= uwsgi.numproc; i++) { + if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) { + decheaped++; + if (decheaped >= uwsgi.cheaper_step) break; + } } } @@ -271,15 +272,15 @@ int cheaper_busyness_algo(void) { uwsgi_log("[busyness] %llus average busyness is at %llu%%, will spawn %d new worker(s)\n", uwsgi.cheaper_overload, avg_busyness, decheaped); } else { - uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers (%d)\n", - uwsgi.cheaper_overload, avg_busyness, uwsgi.numproc); + uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers available with current limits (%d)\n", + uwsgi.cheaper_overload, avg_busyness, active_workers); } // return the maximum number of workers to spawn return decheaped; #ifdef __linux__ - } else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) { + } else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) { return spawn_emergency_worker(backlog); #endif @@ -347,14 +348,14 @@ int cheaper_busyness_algo(void) { } #ifdef __linux__ - else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) { + else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) { // we check for backlog overload every cycle return spawn_emergency_worker(backlog); } else if (backlog > 0) { if (uwsgi_cheaper_busyness_global.backlog_is_nonzero) { // backlog was > 0 last time, check timestamp and spawn workers if needed - if ((now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) { + if (can_spawn && (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) { uwsgi_log("[busyness] backlog was non-zero for %llu second(s), spawning new worker(s)\n", (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000); uwsgi_cheaper_busyness_global.backlog_nonzero_since = now; return spawn_emergency_worker(backlog); @@ -391,4 +392,3 @@ struct uwsgi_plugin cheaper_busyness_plugin = { .options = uwsgi_cheaper_busyness_options, }; - diff --git a/uwsgi.h b/uwsgi.h index 84384bab..b1cc53c9 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1563,7 +1563,7 @@ struct uwsgi_signal_rb_timer { struct uwsgi_cheaper_algo { char *name; - int (*func) (void); + int (*func) (int); struct uwsgi_cheaper_algo *next; }; @@ -1735,7 +1735,7 @@ struct uwsgi_server { int cheaper; char *requested_cheaper_algo; struct uwsgi_cheaper_algo *cheaper_algos; - int (*cheaper_algo) (void); + int (*cheaper_algo) (int); int cheaper_step; uint64_t cheaper_overload; // minimal number of running workers in cheaper mode @@ -3612,16 +3612,16 @@ void uwsgi_manage_zerg(int, int, int *); time_t uwsgi_now(void); int uwsgi_calc_cheaper(void); -int uwsgi_cheaper_algo_spare(void); -int uwsgi_cheaper_algo_backlog(void); -int uwsgi_cheaper_algo_backlog2(void); -int uwsgi_cheaper_algo_manual(void); +int uwsgi_cheaper_algo_spare(int); +int uwsgi_cheaper_algo_backlog(int); +int uwsgi_cheaper_algo_backlog2(int); +int uwsgi_cheaper_algo_manual(int); int uwsgi_master_log(void); int uwsgi_master_req_log(void); void uwsgi_flush_logs(void); -void uwsgi_register_cheaper_algo(char *, int (*)(void)); +void uwsgi_register_cheaper_algo(char *, int (*)(int)); void uwsgi_setup_locking(void); int uwsgi_fcntl_lock(int);