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:
parent
4c49fae985
commit
9d5f5480fd
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user