Nginx learning: memory pool

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

The data structure of nginx management memory pool is ngx_pool_t. In ngx_request_t, the ngx_conf_t controlled ngx_pool_t.

A defined in nginx Ngx_palloc.h:


struct ngx_pool_s {
    ngx_pool_data_t       d;
    size_t                max;
    ngx_pool_t           *current;
    ngx_chain_t          *chain;
    ngx_pool_large_t     *large;
    ngx_pool_cleanup_t   *cleanup;
    ngx_log_t            *log;
};

typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_t;

Last has been used at the end of the block of memory to the current, end points to the current block of memory at the end, next refers to a block of memory, nginx is using memory pool chain table.


typedef struct ngx_pool_large_s  ngx_pool_large_t;

struct ngx_pool_large_s {
    ngx_pool_large_t     *next;
    void                 *alloc;
};
When the allocated memory pool size is more than NGX_MAX_ALLOC_FROM_POOL, a pointer to the memory pool to keep a copy of this structure. The benefits of doing so is to
struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;
    void                 *data;
    ngx_pool_cleanup_t   *next;
};

Save the need to clean up the data pointer and the corresponding cleanup function in this result, let the memory pool destruction

Two. The correlation function control memory pool

ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
void ngx_destroy_pool(ngx_pool_t *pool);
void ngx_reset_pool(ngx_pool_t *pool);

void *ngx_palloc(ngx_pool_t *pool, size_t size);
void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);


ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);
void ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd);
void ngx_pool_cleanup_file(void *data);
void ngx_pool_delete_file(void *data);

2.1 note and Ngx_alloc.h void *ngx_alloc (size_t size, ngx_log_t *log); and void *ngx_calloc (size_t size, ngx_log_t *log) to distinguish

According to the definition:


ngx_alloc(size_t size, ngx_log_t *log)
{
    void  *p;

    p = malloc(size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "malloc(%uz) failed", size);
    }

    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);

    return p;
}


void *
ngx_calloc(size_t size, ngx_log_t *log)//initial the ngx_alloc
{
    void  *p;

    p = ngx_alloc(size, log);

    if (p) {
        ngx_memzero(p, size);
    }

    return p;
}
Ngx_alloc and ngx_calloc just simple encapsulation of alloc and calloc. Ngx_palloc is the control of the memory pool, meaning is completely different.

2.2 the significance of each function

ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);//Create a pool of memory unit, nginx memory pool is connected with a list of the
ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)
{
    ngx_pool_t  *p;

    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);//Memory alignment, interested can look at nginx is how do aligned, do a tricky, nginx visible on the processing of detail. 
    if (p == NULL) {
        return NULL;
    }

    p->d.last = (u_char *) p + sizeof(ngx_pool_t);
    p->d.end = (u_char *) p + size;
    p->d.next = NULL;
    p->d.failed = 0;

    size = size - sizeof(ngx_pool_t);
    p->max = (size <NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;//Size setup cannot be more than NGX_MAX_ALLOC_FROM_POOL

    p->current = p;
    p->chain = NULL;
    p->large = NULL;
    p->cleanup = NULL;
    p->log = log;

    return p;
}

void ngx_destroy_pool(ngx_pool_t *pool);//Clear memory pool structure, here cleaning objects including cleanup, large and D. 
void
ngx_destroy_pool(ngx_pool_t *pool)
{
    ngx_pool_t          *p, *n;
    ngx_pool_large_t    *l;
    ngx_pool_cleanup_t  *c;

    for (c = pool->cleanup; c; c = c->next) {
        if (c->handler) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "run cleanup: %p", c);
            c->handler(c->data);
        }
    }

    for (l = pool->large; l; l = l->next) {

        ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc);

        if (l->alloc) {
            ngx_free(l->alloc);
        }
    }

#if (NGX_DEBUG)

    /*
     * we could allocate the pool->log from this pool
     * so we cannot use this log while free()ing the pool
     */

    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
        ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                       "free: %p, unused: %uz", p, p->d.end - p->d.last);

        if (n == NULL) {
            break;
        }
    }

#endif

    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
        ngx_free(p);

        if (n == NULL) {
            break;
        }
    }
}


void ngx_reset_pool(ngx_pool_t *pool);//According to the literal reset, this function is a pool reset. 
void
ngx_reset_pool(ngx_pool_t *pool)
{
    ngx_pool_t        *p;
    ngx_pool_large_t  *l;

    for (l = pool->large; l; l = l->next) {
        if (l->alloc) {
            ngx_free(l->alloc);
        }
    }

    for (p = pool; p; p = p->d.next) {
        p->d.last = (u_char *) p + sizeof(ngx_pool_t);//Ngx_pool_t itself takes up a memory
        p->d.failed = 0;
    }

    pool->current = pool;
    pool->chain = NULL;
    pool->large = NULL;
}


void *ngx_palloc(ngx_pool_t *pool, size_t size);//A part from the allocated memory pool
void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    ngx_pool_t  *p;

    if (size <= pool->max) {

        p = pool->current;

        do {
            m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);//alignment 

            if ((size_t) (p->d.end - m) >= size) {
                p->d.last = m + size;

                return m;
            }

            p = p->d.next;

        } while (p);

        return ngx_palloc_block(pool, size);//Failed to get a piece of memory pool, redistribution
    }

    return ngx_palloc_large(pool, size);//Failed to get the redistribution, a large memory pool
}


void *ngx_pnalloc(ngx_pool_t *pool, size_t size);//With the ngx_palloc difference is: ngx_pnalloc access memory will not consider the alignment situation. 
void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    ngx_pool_t  *p;

    if (size <= pool->max) {

        p = pool->current;

        do {
            m = p->d.last;//Get behind, without considering the alignment

            if ((size_t) (p->d.end - m) >= size) {
                p->d.last = m + size;

                return m;
            }

            p = p->d.next;

        } while (p);

        return ngx_palloc_block(pool, size);
    }

    return ngx_palloc_large(pool, size);
}


void *ngx_pcalloc(ngx_pool_t *pool, size_t size);//Distribution of the mgx_palloc memory is initialized
void *
ngx_pcalloc(ngx_pool_t *pool, size_t size)
{
    void *p;

    p = ngx_palloc(pool, size);
    if (p) {
        ngx_memzero(p, size);
    }

    return p;
}


static void *ngx_palloc_large(ngx_pool_t *pool, size_t size);//Allocate a large block of memory
static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)

{
    void              *p;
    ngx_uint_t         n;
    ngx_pool_large_t  *large;


    p = ngx_alloc(size, pool->log);
    if (p == NULL) {
        return NULL;
    }


    n = 0;


    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {
            large->alloc = p;
            return p;
        }


        if (n++ > 3) {
            break;
        }
    }


    large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }


    large->alloc = p;
    large->next = pool->large;//put in the head???
    pool->large = large;


    return p;
}


void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);//Allocate a large block of memory, compared with ngx_palloc_large, increasing the alignment function. 
void *
ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
{
    void              *p;
    ngx_pool_large_t  *large;


    p = ngx_memalign(alignment, size, pool->log);
    if (p == NULL) {
        return NULL;
    }


    large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }


    large->alloc = p;
    large->next = pool->large;
    pool->large = large;


    return p;
}



ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);//Small memory with the destroy release, but the bulk memory free can be used to release. 
ngx_int_t
ngx_pfree(ngx_pool_t *pool, void *p)
{
    ngx_pool_large_t  *l;


    for (l = pool->large; l; l = l->next) {
        if (p == l->alloc) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "free: %p", l->alloc);
            ngx_free(l->alloc);
            l->alloc = NULL;


            return NGX_OK;
        }
    }


    return NGX_DECLINED;
}


ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);//A section of memory allocation and registration
ngx_pool_cleanup_t *
ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
{
    ngx_pool_cleanup_t  *c;


    c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t));
    if (c == NULL) {
        return NULL;
    }


    if (size) {
        c->data = ngx_palloc(p, size);
        if (c->data == NULL) {
            return NULL;//There may be further optimized, because data allocation failure, should be immediately free off the C share memory. 
        }


    } else {
        c->data = NULL;
    }


    c->handler = NULL;
    c->next = p->cleanup;//put int header


    p->cleanup = c;


    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c);


    return c;
}

Three functions and documents related to the following, no longer tired. 
void ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd);

void ngx_pool_cleanup_file(void *data);

void ngx_pool_delete_file(void *data);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Brendan at February 22, 2014 - 11:35 AM