From 75f3da76e48df79c21e65354768d3f581053127e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 16 Aug 2011 18:20:51 -0400 Subject: s3-prefork: Improve heuristics Signed-off-by: Andreas Schneider Signed-off-by: Simo Sorce --- source3/lib/server_prefork.c | 11 ++++--- source3/lib/server_prefork.h | 8 ++--- source3/lib/server_prefork_util.c | 63 +++++++++++++++++++++++++-------------- 3 files changed, 52 insertions(+), 30 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/server_prefork.c b/source3/lib/server_prefork.c index 71441c3303..d63e6a1673 100644 --- a/source3/lib/server_prefork.c +++ b/source3/lib/server_prefork.c @@ -279,7 +279,7 @@ int prefork_retire_children(struct prefork_pool *pfp, return j; } -int prefork_count_active_children(struct prefork_pool *pfp, int *total) +int prefork_count_children(struct prefork_pool *pfp, int *active) { int i, a, t; @@ -292,15 +292,18 @@ int prefork_count_active_children(struct prefork_pool *pfp, int *total) t++; - if (pfp->pool[i].num_clients <= 0) { + if ((pfp->pool[i].status == PF_WORKER_EXITING) || + (pfp->pool[i].num_clients <= 0)) { continue; } a++; } - *total = t; - return a; + if (active) { + *active = a; + } + return t; } static void prefork_cleanup_loop(struct prefork_pool *pfp) diff --git a/source3/lib/server_prefork.h b/source3/lib/server_prefork.h index 334b5813a0..d240641a39 100644 --- a/source3/lib/server_prefork.h +++ b/source3/lib/server_prefork.h @@ -168,14 +168,14 @@ int prefork_add_children(struct tevent_context *ev_ctx, int prefork_retire_children(struct prefork_pool *pfp, int num_children, time_t age_limit); /** -* @brief Count the number of active children +* @brief Count the number of children * * @param pfp The pool. -* @param total Returns the number of children currently alive +* @param active Number of children currently active if not NULL * -* @return The number of children actually serving clients +* @return The total number of children. */ -int prefork_count_active_children(struct prefork_pool *pfp, int *total); +int prefork_count_children(struct prefork_pool *pfp, int *active); /** * @brief Count the number of actual connections currently allowed diff --git a/source3/lib/server_prefork_util.c b/source3/lib/server_prefork_util.c index 8d7d0d2bb5..638ce66f09 100644 --- a/source3/lib/server_prefork_util.c +++ b/source3/lib/server_prefork_util.c @@ -65,7 +65,7 @@ void pfh_manage_pool(struct tevent_context *ev_ctx, struct prefork_pool *pool) { time_t now = time(NULL); - int active, total; + int total, avail; int ret, n; if ((cfg->prefork_status & PFH_NEW_MAX) && @@ -77,43 +77,62 @@ void pfh_manage_pool(struct tevent_context *ev_ctx, cfg->prefork_status &= ~PFH_NEW_MAX; } - active = prefork_count_active_children(pool, &total); + total = prefork_count_children(pool, NULL); + avail = prefork_count_allowed_connections(pool); + DEBUG(10, ("(Pre)Stats: children: %d, allowed connections: %d\n", + total, avail)); - if ((total < cfg->max_children) && - ((total < cfg->min_children) || - (total - active < cfg->spawn_rate))) { + if ((total < cfg->max_children) && (avail < cfg->spawn_rate)) { n = prefork_add_children(ev_ctx, msg_ctx, pool, cfg->spawn_rate); if (n < cfg->spawn_rate) { - DEBUG(10, ("Tried to start %d children but only," - "%d were actually started.!\n", + DEBUG(10, ("Attempted to add %d children but only " + "%d were actually added!\n", cfg->spawn_rate, n)); } - } - - if (total - active > cfg->min_children) { - if ((total - cfg->min_children) >= cfg->spawn_rate) { - prefork_retire_children(pool, cfg->spawn_rate, + } else if ((avail - cfg->min_children) >= cfg->spawn_rate) { + /* be a little slower in retiring children, to allow for + * double spikes of traffic to be handled more gracefully */ + n = (cfg->spawn_rate / 2) + 1; + if (n > cfg->spawn_rate) { + n = cfg->spawn_rate; + } + if ((total - n) < cfg->min_children) { + n = total - cfg->min_children; + } + if (n >= 0) { + prefork_retire_children(pool, n, now - cfg->child_min_life); } } - n = prefork_count_allowed_connections(pool); - if (n <= cfg->spawn_rate) { - do { + /* total/avail may have just been changed in the above if/else */ + total = prefork_count_children(pool, NULL); + avail = prefork_count_allowed_connections(pool); + if ((total == cfg->max_children) && (avail < cfg->spawn_rate)) { + n = avail; + while (avail < cfg->spawn_rate) { prefork_increase_allowed_clients(pool, cfg->max_allowed_clients); - n = prefork_count_allowed_connections(pool); - } while (n <= cfg->spawn_rate); - } else if (n > cfg->max_children + cfg->spawn_rate) { - do { + avail = prefork_count_allowed_connections(pool); + /* if avail didn't change do not loop forever */ + if (n == avail) break; + n = avail; + } + } else if (avail > total + cfg->spawn_rate) { + n = avail; + while (avail > total + cfg->spawn_rate) { prefork_decrease_allowed_clients(pool); - n = prefork_count_allowed_connections(pool); - } while (n > cfg->max_children + cfg->spawn_rate); + avail = prefork_count_allowed_connections(pool); + /* if avail didn't change do not loop forever */ + if (n == avail) break; + n = avail; + } } DEBUG(10, ("Stats: children: %d, allowed connections: %d\n", - total, prefork_count_allowed_connections(pool))); + prefork_count_children(pool, NULL), + prefork_count_allowed_connections(pool))); } void pfh_client_terminated(struct pf_worker_data *pf) -- cgit