MEDIUM: compression: limit RAM usage

With the global maxzlibmem option, you are able ton control the maximum
amount of RAM usable for HTTP compression.

A test is done before each zlib allocation, if the there isn't available
memory, the test fail and so the zlib initialization, so data won't be
compressed.
This commit is contained in:
William Lallemand 2012-11-07 16:12:57 +01:00 committed by Willy Tarreau
parent 4c49fae985
commit 9d5f5480fd
5 changed files with 43 additions and 8 deletions

View File

@ -688,6 +688,12 @@ maxsslconn <number>
that the limit applies both to incoming and outgoing connections, so one
connection which is deciphered then ciphered accounts for 2 SSL connections.
maxzlibmem <number>
Sets the maximum amount of RAM in megabytes per process usable by the zlib.
When the maximum amount is reached, future sessions will not compress as long
as RAM is unavailable. When sets to 0, there is no limit.
The default value is 0.
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

View File

@ -85,6 +85,7 @@ struct global {
int maxsock; /* max # of sockets */
int rlimit_nofile; /* default ulimit-n value : 0=unset */
int rlimit_memmax; /* default ulimit-d in megs value : 0=unset */
int maxzlibmem; /* max RAM for zlib in megs */
int mode;
unsigned int req_count; /* HTTP request counter */
int last_checks;

View File

@ -841,6 +841,14 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
}
global.maxpipes = atol(args[1]);
}
else if (!strcmp(args[0], "maxzlibmem")) {
if (*(args[1]) == 0) {
Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
global.maxzlibmem = atol(args[1]);
}
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]);

View File

@ -43,6 +43,9 @@ static struct pool_head *zlib_pool_prev = NULL;
static struct pool_head *zlib_pool_head = NULL;
static struct pool_head *zlib_pool_pending_buf = NULL;
static long long zlib_memory_available = -1;
#endif
@ -341,6 +344,11 @@ static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
static char round = 0; /* order in deflateInit2 */
void *buf = NULL;
if (global.maxzlibmem > 0 && zlib_memory_available < items * size){
buf = NULL;
goto end;
}
switch (round) {
case 0:
if (zlib_pool_deflate_state == NULL)
@ -372,6 +380,10 @@ static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
ctx->zlib_pending_buf = buf = pool_alloc2(zlib_pool_pending_buf);
break;
}
if (buf != NULL && global.maxzlibmem > 0)
zlib_memory_available -= items * size;
end:
round = (round + 1) % 5; /* there are 5 zalloc call in deflateInit2 */
return buf;
@ -380,18 +392,22 @@ static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
static void free_zlib(void *opaque, void *ptr)
{
struct comp_ctx *ctx = opaque;
struct pool_head *pool;
if (ptr == ctx->zlib_window)
pool_free2(zlib_pool_window, ptr);
pool = zlib_pool_window;
else if (ptr == ctx->zlib_deflate_state)
pool_free2(zlib_pool_deflate_state, ptr);
pool = zlib_pool_deflate_state;
else if (ptr == ctx->zlib_prev)
pool_free2(zlib_pool_prev, ptr);
pool = zlib_pool_prev;
else if (ptr == ctx->zlib_head)
pool_free2(zlib_pool_head, ptr);
pool = zlib_pool_head;
else if (ptr == ctx->zlib_pending_buf)
pool_free2(zlib_pool_pending_buf, ptr);
pool = zlib_pool_pending_buf;
pool_free2(pool, ptr);
if (global.maxzlibmem > 0)
zlib_memory_available += pool->size;
}
@ -402,6 +418,9 @@ int gzip_init(struct comp_ctx *comp_ctx, int level)
{
z_stream *strm = &comp_ctx->strm;
if (global.maxzlibmem > 0 && zlib_memory_available < 0)
zlib_memory_available = global.maxzlibmem * 1024 * 1024; /* Megabytes to bytes */
strm->zalloc = alloc_zlib;
strm->zfree = free_zlib;
strm->opaque = comp_ctx;
@ -487,10 +506,10 @@ int deflate_end(struct comp_ctx *comp_ctx)
{
z_stream *strm = &comp_ctx->strm;
if (deflateEnd(strm) == Z_OK)
return 0;
if (deflateEnd(strm) != Z_OK)
return -1;
return -1;
return 0;
}
#endif /* USE_ZLIB */

View File

@ -112,6 +112,7 @@ int relative_pid = 1; /* process id starting at 1 */
struct global global = {
.req_count = 0,
.logsrvs = LIST_HEAD_INIT(global.logsrvs),
.maxzlibmem = 0,
.unix_bind = {
.ux = {
.uid = -1,