summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2011-08-16 18:20:51 -0400
committerSimo Sorce <idra@samba.org>2011-08-21 09:05:05 -0400
commit75f3da76e48df79c21e65354768d3f581053127e (patch)
treebdc84c408d80a121f9231114129f87980db0940a /source3/lib
parent89dde6b7fce3342c828f166e7d76bf4656939ee4 (diff)
downloadsamba-75f3da76e48df79c21e65354768d3f581053127e.tar.gz
samba-75f3da76e48df79c21e65354768d3f581053127e.tar.bz2
samba-75f3da76e48df79c21e65354768d3f581053127e.zip
s3-prefork: Improve heuristics
Signed-off-by: Andreas Schneider <asn@samba.org> Signed-off-by: Simo Sorce <idra@samba.org>
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/server_prefork.c11
-rw-r--r--source3/lib/server_prefork.h8
-rw-r--r--source3/lib/server_prefork_util.c63
3 files changed, 52 insertions, 30 deletions
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)