Nginx Memory Pool Management

Source: Internet
Author: User

Overview

Nginx uses memory pool to manage memory, memory management implementation is similar to the previous article introduced the "STL Source analysis-Space Configurator", the memory allocation to large memory allocation and small memory allocation. If the requested memory size is larger than the maximum memory pool max for the same page, it is a large memory allocation, otherwise small memory allocation.

    1. The allocation request for large chunks of memory does not allocate memory directly to the memory pool to satisfy the request, but instead requests a piece of memory directly to the system (just like allocating memory directly using malloc) and then hangs the memory into the large field of the memory pool header.
    2. A small chunk of memory allocation is the allocation of a portion of memory from an existing memory pool data area.

Nginx memory Management related files:

    1. Src/os/unix/ngx_alloc.h/.c
      • Memory-related operations, encapsulating the most basic memory allocation functions.
      • such as Free/malloc/memalign/posix_memalign, respectively, are encapsulated as Ngx_free,ngx_alloc/ngx_calloc, ngx_memalign
        • Ngx_alloc: Encapsulating malloc allocating memory
        • Ngx_calloc: Encapsulates malloc allocates memory and initializes 0 of the space content
        • Ngx_memalign: Returns the size of a memory space based on a specified alignment with an integer multiple of alignment and a power of alignment of 2.
    2. Src/core/ngx_palloc.h/.c
      • Encapsulates functions such as creating/destroying memory pools, allocating space from memory pools, and so on.
The Nginx memory allocation total flow graph is as follows: where size is the amount of memory the user requests to allocate,pool is the existing memory pool.

Memory pool Basic Structure
Nginx Memory pool basic structure is defined as follows:
/* Memory pool structure *//* file core/ngx_palloc.h */typedef struct {/* Memory pool data Structure module */    U_char               *last;/* The end of the current memory allocation, that is, the starting position of the next allocated memory * /    U_char               *end;  /* The end location of the memory pool */    ngx_pool_t           *next;/* point to the next memory pool */    ngx_uint_t            failed;/* log memory pool memory allocation failed */} Ngx_pool_data_ t;  /* Maintain the memory pool data block */struct ngx_pool_s {/* Memory pool management module, i.e. memory pool header structure */    ngx_pool_data_t       D;    /* data block for memory pool */    size_t                Max;  /* max value of memory pool data block */    ngx_pool_t           *current;/* point to current memory pool */    ngx_chain_t          *chain;/* point to a ngx_chain_t structure */    ngx_pool_large_t     *large;/* Large memory linked list, that is, allocating more than max memory */    ngx_pool_cleanup_t   *cleanup;/* destructor, free memory pool */    ngx_log_t            *log;/* memory allocation related log information */};/* file core/ngx_core.h */typedef struct ngx_pool_s   ngx_pool_t; typedef struct NGX_CHAIN_S  ngx_chain_t;

The data structure for bulk memory allocation is as follows:
typedef struct NGX_POOL_LARGE_S ngx_pool_large_t;  struct ngx_pool_large_s{            ngx_pool_large_t  *next;    Point to the next chunk of memory            void    *alloc;             Point to the allocated chunk of memory  };  

Other data structures are as follows:
typedef void (*NGX_POOL_CLEANUP_PT) (void *data);    Cleanup callback type  typedef struct NGX_POOL_CLEANUP_S ngx_pool_cleanup_t;   struct ngx_pool_cleanup_s{      ngx_pool_cleanup_pt handler;      void    *data;              Point to the data to be purged      ngx_pool_cleanup_t *next;   Next cleanup callback  };     typedef struct {      ngx_fd_t   fd;      U_char    *name;      ngx_log_t *log;  } ngx_pool_cleanup_file_t;  

The relationship between the memory pool base mechanism is as follows:
the logical structure of ngx_pool_t

The logical structure diagram between the above data structures is as follows: the diagram is a UML painting, the first line of black bold representation of the corresponding data structure, the second row is a member of the structure, the left side of the colon is a variable, the right side of the colon is the type of variable;



Operation of the memory pool Create a memory pool
/* Create a memory pool that is defined in the src/core/ngx_palloc.c file */ngx_pool_t *ngx_create_pool (size_t size, ngx_log_t *log) {    ngx_pool_t  *p;/* Execute Memory Pool Header/*/*    Allocate memory size to */    * * Ngx_memalign function implemented in SRC/OS/UNIX/NGX_ALLOC.C file */    p = ngx_memal IGN (ngx_pool_alignment, size, log);    if (p = = null) {        return null;    }    /* The following is the initialization of the NGX_POOL_T structure information *    /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);   /* The space size to allocate *    /* cannot exceed the maximum limit of 4096B *    /P->max = (Size < Ngx_max_alloc_from_pool)? size:ngx_max_alloc_fr Om_pool;    P->current = p; /* point to the current memory pool */    p->chain = NULL;    P->large = NULL;    P->cleanup = NULL;    P->log = log;    return p;}

Where the memory allocation function ngx_memalign is defined as follows:
void *  ngx_memalign (size_t alignment, size_t size, ngx_log_t *log)  {      void  *p;      int    err;            Err = posix_memalign (&p, alignment, size);      The function allocates the memory size of a size byte that is aligned with alignment, where p points to the allocated memory block.            if (err) {          ngx_log_error (Ngx_log_emerg, log, err,              "Posix_memalign (%uz,%uz) failed", alignment, size); C11/>p = NULL;      }            NGX_LOG_DEBUG3 (ngx_log_debug_alloc, log, 0,          "posix_memalign:%p:%uz @%uz", p, size, alignment);            return p;  }  The function allocates the memory of size bytes aligned in ngx_pool_alignment Byte, in the src/core/ngx_palloc.h file:  #define Ngx_pool_alignment       16  

Destroying the memory pool destroys the memory pool that is done by the void Ngx_destroy_pool (ngx_pool_t *pool) function. This function iterates through the memory pool chain list, frees all memory, and, if registered with Clenup (also a linked list structure), iterates over the cleanup list structure and calls Clenup handler cleanup in turn. At the same time, it will traverse the large linked list and release large chunks of memory.
/* Destroy Memory Pool */voidngx_destroy_pool (ngx_pool_t *pool) {ngx_pool_t *p, *n;    ngx_pool_large_t *l;    ngx_pool_cleanup_t *c; /* If cleanup is registered, iterate through the list structure and call the handler function cleanup data sequentially */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); }//* Traverse the large list to free large chunks of memory */for (L = pool->large; l; l = l->next) {NGX_LOG_DEBUG1 (Ngx_log_debug_al        LOC, Pool->log, 0, "Free:%p", L->alloc); if (l->alloc) {ngx_free (L-&GT;ALLOC);/* Free memory */}}/* Execute code between if and endif in debug mode; * Main is used for log records, trace function destruction logs information */#if (NGX_DEBUG)/* * We could allocate the pool->log from this pool * so we canno  T use this log and 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/* Traverse all allocated memory pools, free the memory pool structure */for (p = pool, n = pool->d.next; */void */; p = n, n = n->d.next) {        Ngx_free (P);        if (n = = NULL) {break; }    }}


Resetting the memory pool resetting the memory pool is done by the void Ngx_reset_pool (ngx_pool_t *pool) function. This function frees all large memory and d->last the pointer back to the beginning of the data area after the ngx_pool_t structure, restoring the memory pool to its location when it was just created. Large chunks of memory must be freed because the memory pool has just been created to initialize without large chunks of memory.
/* Reset the memory pool * defined in the src/core/ngx_palloc.c file */voidngx_reset_pool (ngx_pool_t *pool) {    ngx_pool_t        *p;    ngx_pool_large_t  *l;    /* Traverse large memory linked list to free large chunks of memory *    /for (L = pool->large; l; l = l->next) {        if (l->alloc) {            ngx_free (l->alloc); c8/>}    } for    (p = pool; p; p = p->d.next) {        P->d.last = (U_char *) p + sizeof (ngx_pool_t);        p->d.failed = 0;    }    Pool->current = pool;    Pool->chain = NULL;    Pool->large = NULL;}

Memory allocation small block memory allocation small block memory allocation, that is, the request allocation space size is less than the memory pool maximum memory value max. The interface functions for small memory allocations are as follows:
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);

Both Ngx_palloc and Ngx_pnalloc allocate size memory from the memory pool. Their difference is that the memory obtained by PALLOC is aligned, and Pnalloc does not consider the memory alignment problem. Ngx_pcalloc is to directly call Palloc to allocate memory and then perform a 0 initialization operation. Ngx_pmemalign will allocate the size of the memory and press alignment to align, and then hang to the large field, as a chunk of memory processing.
/* Allocate memory */void *ngx_palloc (ngx_pool_t *pool, size_t size) {U_char *m;    ngx_pool_t *p; /* If the requested memory size is less than the memory pool Max memory Value Max, * The process small memory allocation is traversed from current to the pool list */if (size <= pool->max) {p = pool-&        Gt;current;            Do {/* Perform alignment operation */M = ngx_align_ptr (P->d.last, ngx_alignment); /* Check that the existing memory pool has sufficient memory space, * if there is enough memory space, move the last pointer position, * and return the start address of the allocated memory address */if (s   ize_t) (p->d.end-m) >= size) {p->d.last = m + size;            /* Allocate a size memory */return m in the memory block pointed to by the node;        }/* If not met, find the next memory pool */p = p->d.next;        } while (P); /* If there is no memory space available to traverse all existing memory Chiling, * Allocate a new memory pool and connect the memory pool to the existing memory pool linked list * Return the start address of the allocated memory */return NGX_PA    Lloc_block (pool, size); }/* If the requested memory size is larger than Max, the bulk memory allocation function is called */return Ngx_palloc_large (pool, size);} static void *ngx_palloc_block (ngx_pool_t *pool, size_t size) {U_char     *m;    size_t psize;    ngx_pool_t *p, *new, *current;    /* Calculate the size of the pool, i.e. the size of the new block that needs to be allocated */psize = (size_t) (Pool->d.end-(U_char *) pool);    /* ngx_pool_alignment Alignment operation */M = ngx_memalign (Ngx_pool_alignment, psize, Pool->log);    if (M = = null) {return null;    }/* Calculates the size of the block that needs to be allocated */new = (ngx_pool_t *) m;    New->d.end = m + psize;    New->d.next = NULL;    new->d.failed = 0;    /* Initialize the new memory pool */* Let M point to the block memory ngx_pool_data_t structure after the data area starting position */m + = sizeof (ngx_pool_data_t);    /* Allocate a size memory in the data area and set the last pointer */m = ngx_align_ptr (M, ngx_alignment);    New->d.last = m + size;    Current = pool->current; for (p = current; p->d.next; p = p->d.next) {if (p->d.failed++ > 4) {/* * fails 4 times        */current = p->d.next;    }/* Connect the allocated block to the existing memory pool */p->d.next = new; /* If the block is allocated for the memory pool for the first time, this current will point to the newly allocated block */Pool->current =??    Current:new; return m;}

/* Call the Palloc function directly, and then perform a 0 initialization operation */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;} /* Allocate size memory according to alignment, and then hang it into large field as chunk memory processing */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;}
Small memory allocations are as follows: bulk memory allocation
/* Allocate large memory */static void *ngx_palloc_large (ngx_pool_t *pool, size_t size) {void *p;    ngx_uint_t N;    ngx_pool_large_t *large;    /* Allocate memory */p = ngx_alloc (size, pool->log);    if (p = = null) {return null;    } n = 0; /* If the large field has been assigned before the pool, * mount the allocated chunk of memory to the large field in the memory pool */for (large = pool->large; large; large = large->            Next) {if (Large->alloc = = NULL) {large->alloc = P;        return p;        } if (n++ > 3) {break; }}/* If the large field is not assigned before the pool, * Assign ngx_pool_large_t struct, allocate large field memory, and then mount the chunk memory in the large field of the pool */lar    GE = 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;}    void *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 bytes failed", size);    } ngx_log_debug2 (Ngx_log_debug_alloc, log, 0, "malloc:%p:%uz", p, size); return p;}    /* Release large chunks of memory */ngx_int_tngx_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;}
The bulk memory request is then as follows: Cleanup resources
/* Register cleanup; * Size is the resource that the data field points to, */ngx_pool_cleanup_t * Ngx_pool_cleanup_add (ngx_pool_t *p, size_t size);/* to the memory pool File cleanup operation, i.e. execution of handler, at which time handler==ngx_pool_cleanup_file */void Ngx_pool_run_cleanup_file (ngx_pool_t *p, ngx_fd_t FD);/* Closes the file handle specified by data */void Ngx_pool_cleanup_file (void *data);/* Deletes the file specified by data */void Ngx_pool_delete_file (void *data);    /* Register cleanup */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;    }} else {c->data = NULL;    } C->handler = NULL;    C->next = p->cleanup;    P->cleanup = C;    NGX_LOG_DEBUG1 (Ngx_log_debug_alloc, P->log, 0, "Add Cleanup:%p", c); return c;}    /* Clean the memory pool file */voidngx_pool_run_cleanup_file (ngx_pool_t *p, ngx_fd_t fd) {ngx_pool_cleanup_t *c; Ngx_pool_cleanup_file_t *CF; /* Traverse the cleanup structure list and execute handler */for (c = p->cleanup; C; c = c->next) {if (C->handler = = Ngx_pool_cleanu            P_file) {CF = c->data;                if (cf->fd = = FD) {c->handler (CF);                C->handler = NULL;            Return }}}}/* close data specified file handle */voidngx_pool_cleanup_file (void *data) {ngx_pool_cleanup_file_t *c = data;/* point to data    The file handle pointed to */NGX_LOG_DEBUG1 (ngx_log_debug_alloc, C->log, 0, "File cleanup:fd:%d", C-&GT;FD); /* Close the specified file */if (ngx_close_file (c->fd) = = Ngx_file_error) {ngx_log_error (Ngx_log_alert, C->log, Ngx_errno    , ngx_close_file_n "\"%s\ "Failed", C->name);    }}/* Delete the file pointed to by data */voidngx_pool_delete_file (void *data) {ngx_pool_cleanup_file_t *c = data;    ngx_err_t err; Ngx_log_debug2 (Ngx_log_debug_alloc, C->log, 0, "file cleanup:fd:%d%s", C-&GT;FD, C->name);        /* Delete the file pointed to by data */if (ngx_delete_file (c->name) = = Ngx_file_error) {err = Ngx_errno;  if (err! = ngx_enoent) {ngx_log_error (Ngx_log_crit, C->log, err, Ngx_delete_file_n        "\"%s\ "Failed", C->name);  }/* Close file Handle */if (ngx_close_file (c->fd) = = Ngx_file_error) {ngx_log_error (Ngx_log_alert, C->log,    Ngx_errno, ngx_close_file_n "\"%s\ "Failed", C->name); }}

Reference: "Nginx source analysis of memory pool, and memory management" "Nginx Source analysis-memory pool structure ngx_pool_t and memory management," Nginx memory pool implementation of source analytics "Nginx Source analysis-Memory Pool" "NINGX Code Research"

Nginx Memory Pool Management

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.