diff --git a/doc/configuration.txt b/doc/configuration.txt index 2229dde53..3af744419 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -456,6 +456,7 @@ The following keywords are supported in the "global" section : - maxconn - maxconnrate - maxcomprate + - maxcompcpuusage - maxpipes - maxsslconn - noepoll @@ -697,6 +698,16 @@ maxcomprate tune.comp.maxlevel. A value of zero means there is no limit, this is the default value. +maxcompcpuusage + Sets the maximum CPU usage HAProxy can reach before stopping the compression + for new requests or decreasing the compression level of current requests. + It works like 'maxcomprate' but measures CPU usage instead of incoming data + bandwidth. The value is expressed in percent of the CPU used by haproxy. In + case of multiple processes (nbproc > 1), each process manages its individual + usage. A value of 100 disable the limit. The default value is 100. Setting + a lower value will prevent the compression work from slowing the whole + process down and from introducing high latencies. + maxpipes Sets the maximum per-process number of pipes to . Currently, pipes are only used by kernel-based tcp splicing. Since a pipe contains two file @@ -722,7 +733,6 @@ maxzlibmem with "show info" on the line "MaxZlibMemUsage", the memory used by zlib is "ZlibMemUsage" in bytes. - noepoll Disables the use of the "epoll" event polling system on Linux. It is equivalent to the command-line argument "-de". The next polling system diff --git a/include/proto/compression.h b/include/proto/compression.h index 0eaa21604..a2e80b801 100644 --- a/include/proto/compression.h +++ b/include/proto/compression.h @@ -25,6 +25,8 @@ #include +extern unsigned int compress_min_idle; + int comp_append_type(struct comp *comp, const char *type); int comp_append_algo(struct comp *comp, const char *algo); @@ -40,6 +42,7 @@ int identity_reset(struct comp_ctx *comp_ctx); int identity_end(struct comp_ctx **comp_ctx); + #ifdef USE_ZLIB extern long zlib_used_memory; diff --git a/src/cfgparse.c b/src/cfgparse.c index 1fe270894..d173e65fa 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -887,6 +887,20 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) } global.maxzlibmem = atol(args[1]) * 1024L * 1024L; } + else if (!strcmp(args[0], "maxcompcpuusage")) { + if (*(args[1]) == 0) { + Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + compress_min_idle = 100 - atoi(args[1]); + if (compress_min_idle < 0 || compress_min_idle > 100) { + Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } +} + else if (!strcmp(args[0], "ulimit-n")) { if (global.rlimit_nofile != 0) { Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]); diff --git a/src/compression.c b/src/compression.c index 2dc893aa5..0459aa301 100644 --- a/src/compression.c +++ b/src/compression.c @@ -51,6 +51,7 @@ long zlib_used_memory = 0; #endif +unsigned int compress_min_idle = 0; static struct pool_head *pool_comp_ctx = NULL; @@ -560,21 +561,19 @@ int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out, int flag) out_len = (out->size - buffer_len(out)) - strm->avail_out; out->i += out_len; - /* compression rate limit */ - if (global.comp_rate_lim > 0) { - - if (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim) { - /* decrease level */ - if (comp_ctx->cur_lvl > 0) { - comp_ctx->cur_lvl--; - deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY); - } - - } else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel) { - /* increase level */ - comp_ctx->cur_lvl++ ; + /* compression limit */ + if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */ + (idle_pct < compress_min_idle)) { /* idle */ + /* decrease level */ + if (comp_ctx->cur_lvl > 0) { + comp_ctx->cur_lvl--; deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY); } + + } else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel) { + /* increase level */ + comp_ctx->cur_lvl++ ; + deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY); } return out_len; diff --git a/src/proto_http.c b/src/proto_http.c index 8588b50e5..e5b0fb613 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2099,6 +2099,10 @@ int select_compression_response_header(struct session *s, struct buffer *res) if (read_freq_ctr(&global.comp_bps_in) > global.comp_rate_lim) goto fail; + /* limit cpu usage */ + if (idle_pct < compress_min_idle) + goto fail; + /* initialize compression */ if (s->comp_algo->init(&s->comp_ctx, global.tune.comp_maxlevel) < 0) goto fail;