Nginx High-level data structure source analysis (iv)-----memory pool

Source: Internet
Author: User
the use of memory pools brings many benefits to nginx, such as ease of use of memory, simplification of logic code, and improvement of program performance.

Several key points of knowledge are listed below:

(1) function Ngx_palloc () when trying to allocate size memory from memory, in two cases, a size smaller than Pool->max, called a small block memory allocation, if the current memory pool node is smaller than size, then request a new equivalent size memory pool node, Then allocate a size memory space from this new memory pool node. If the size is greater than Pool->max, the large chunk of memory is allocated, and the function that is called immediately requests large chunks of memory from the operating system.

(2) The application of the small block memory is inserted in the tail node of the linked list, while the new chunk memory is inserted in front of the linked list.

(3) Nginx only provides the release of large chunks of memory, does not provide the release of small chunks of memory, meaning that the memory allocated from the memory pool will not be back to the memory pool, and only when the entire memory pool is destroyed, the memory will be recycled into the system memory.

(4) Current field in ngx_pool_t: This field records the starting node for allocating memory from the memory pool, and nginx specifies that when the total number of failed allocations for a memory node is greater than or equal to 6, current points to the next memory node.

(5) Why the maximum value of the Pool->max field is limited to one page of memory, which is also the critical of small chunks of memory and large chunks of memory, because only if the allocated space is less than one page is necessary to cache, otherwise it is not as good as directly using the System interface malloc () to the operating system application.

Definitions of individual structures:

Bulk memory management structure  struct ngx_pool_large_s {      ngx_pool_large_t     *next;   Connect the next large memory management      void                 *alloc;  The large memory address of the application  };    Data Management  typedef struct {      U_char *last in memory pool               ;   The starting address of the available memory      U_char               *end;    The end address of the available memory      ngx_pool_t           *next;   Points to the next memory pool node     ngx_uint_t            failed;//application, the number of failures  } ngx_pool_data_t;    Memory Pool  struct ngx_pool_s {      ngx_pool_data_t       D;       Store data      size_t                max;      The available memory size for the data, up to 1 pages      ngx_pool_t           *current;//points to memory pool      ngx_chain_t *chain allocated memory          ;      ngx_pool_large_t     *large;   Connect large memory management structure      ngx_pool_cleanup_t   *cleanup;  Clean Object Head      ngx_log_t            *log;  };  
Initialization of the memory pool:

Create a memory pool of size  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);  Applies a size byte memory      if (p = = null) {          return null;      }        P->d.last = (U_char *) p + sizeof (ngx_pool_t);   Point to the available memory start address      p->d.end = (U_char *) p + size;                  Point to the end address of available memory      p->d.next = NULL;                                Initially, the next available memory is null      p->d.failed = 0;                             The memory request failed 0 times        size = size-sizeof (ngx_pool_t);       The actual available size, minus the size of the control structure      P->max = (Size < Ngx_max_alloc_from_pool)? Size:ngx_max_alloc_from_pool;       The maximum can only be one page size        p->current = p;                          Point to the memory pool that is allocating memory      p->chain = NULL;      P->large = NULL;      P->cleanup = NULL;      P->log = log;        return p;  }  
Destruction and reset of the memory pool:

Destroy memory pool void Ngx_destroy_pool (ngx_pool_t *pool) {ngx_pool_t *p, *n;      ngx_pool_large_t *l;        ngx_pool_cleanup_t *c; Run Cleanup Object handler for (c = pool->cleanup; C; c = c->next) {if (C->handler) {Ngx_log_d              EBUG1 (Ngx_log_debug_alloc, Pool->log, 0, "Run Cleanup:%p", c);          C->handler (C->data); }}//Free large memory 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); Use free to release malloc request Memory}} #if (Ngx_debug)/* * We could allocate the pool->log from this P Ool * 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//releases each requested memory pool object ngx_pool_t for (p = pool, n = pool->d.next;/* void */; p = n, n = n->            D.next) {ngx_free (P);          if (n = = NULL) {break;      }}}//reset memory pool void Ngx_reset_pool (ngx_pool_t *pool) {ngx_pool_t *p;        ngx_pool_large_t *l;           Free large memory for (L = pool->large; l; l = l->next) {if (L->alloc) {ngx_free (l->alloc);  }}//Memory pool object, only change last pointer position for (p = pool; p; p = p->d.next) {p->d.last = (U_char   *) p + sizeof (ngx_pool_t);      Causes all memory pool objects to have the same starting address offset for the available memory p->d.failed = 0;      } pool->current = pool;      Pool->chain = NULL;  Pool->large = NULL;   }
Allocating memory:

Allocate memory (address alignment) void * Ngx_palloc (ngx_pool_t *pool, size_t size) {U_char *m;        ngx_pool_t *p;            if (size <= Pool->max) {//Small memory request, with size as standard p = pool->current;  do {m = Ngx_align_ptr (P->d.last, ngx_alignment);//D.last address is aligned first if (size_t) (p->d.end        -m) >= size) {//available memory is greater than the memory to be requested P->d.last = m + size;       Direct update d.last return m;       Direct return} p = p->d.next;            Otherwise, find the next available memory pool object} while (p);      If not found, then to request a new memory pool object return Ngx_palloc_block (pool, size);    } return Ngx_palloc_large (pool, size);      Large memory Request processing}//Allocate memory (address can not be aligned) void * NGX_PNALLOC (ngx_pool_t *pool, size_t size) {U_char *m;        ngx_pool_t *p;            if (size <= Pool->max) {//small memory P = pool->current;                do {m = p->d.last; 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);    Request a new memory pool object} return Ngx_palloc_large (pool, size);   Large Memory}
Small Block memory allocation:

//request a new memory pool object static void * Ngx_palloc_block (ngx_pool_t *pool, size_t size) {U_char *m;      size_t psize;        ngx_pool_t *p, *new;    Psize = (size_t) (Pool->d.end-(U_char *) pool);  The total size of the application memory M = ngx_memalign (Ngx_pool_alignment, psize, Pool->log);      Alignment request Memory if (M = = null) {return null; } new = (ngx_pool_t *) m;      New Memory New->d.end = m + psize;      The last address of the available memory New->d.next = NULL;        new->d.failed = 0;   m + = sizeof (ngx_pool_data_t);      There is only one ngx_pool_data_t, saving the rest of the ngx_pool_t overhead m = ngx_align_ptr (M, ngx_alignment);      New->d.last = m + size; The starting address of the available memory//If the current number of failed requests for memory has been 5 times, for the 6th time, it will point to the new memory pool object for (p = pool->current; p->d.next; p = P          >d.next) {if (p->d.failed++ > 4) {pool->current = p->d.next; }} p->d.next = new;  Connect the memory pool object that just requested return m; }  
Bulk memory allocation

Large memory request processing  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);      Direct malloc requests Memory      if (p = = null) {          return null;      }        n = 0;        for (large = pool->large; large; large = Large->next) {          if (Large->alloc = = NULL) {      ////If memory is freed, re-usable 
  large->alloc = p;                  return p;          }            if (n++ > 3) {       //But only 4 times, 5th Direct break, create large memory management structure break              ;          }      }        Large = Ngx_palloc (pool, sizeof (ngx_pool_large_t)); Request memory from the memory pool object      if (large = = NULL) {          ngx_free (p);          return NULL;      }        Large->alloc = p;    Large memory point to request        //Insert Large header      Large->next = pool->large;          Pool->large = large;        return p;  }  
Allocating memory directly:

Request Memory  void *  ngx_pmemalign (ngx_pool_t *pool, size_t size, size_t alignment)  {      void), no matter how large the memory size is              *p;      ngx_pool_large_t  *large;        p = ngx_memalign (alignment, size, pool->log);    The requested Memory      if (p = = null) {          return null;      }        Large = Ngx_palloc (pool, sizeof (ngx_pool_large_t)); Request a large memory management structure      if (large = = NULL) {          ngx_free (p);          return NULL;      }        Put into the memory pool ngx_pool_t manage      large->alloc = p;    Point to request memory        //insert to head      Large->next = pool->large;      Pool->large = large;        return p;  }  
Free Memory:

Free memory  ngx_int_t  ngx_pfree (ngx_pool_t *pool, void *p)  {      ngx_pool_large_t  *l;        Release only large memory for      (L = pool->large; l; l = l->next) {          if (p = = l->alloc) {              ngx_log_debug1 (ngx_log_debug_al LOC, Pool->log, 0,                             "Free:%p", l->alloc);              Ngx_free (l->alloc);              L->alloc = NULL; Empty                return NGX_OK;          }      }        return ngx_declined;  }  

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

The above describes the Nginx high-level data structure source analysis (iv)-----memory pool, including aspects of the content, I hope to be interested in PHP tutorial friends helpful.

  • 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.