NGINX(二)内存池
2015-10-09 14:40
615 查看
ngxin中为了加快内存分配的速度,引入了内存池, 大块申请, 减少分配次数, 小块分割, 极大的提高了内存申请速度, 另外一个用途就是省去了很多内存管理的任务,因为这里没有提供内存释放的功能,也就是说在pool中分配的内存,只有pool被销毁的时候才能释放掉,真正的还给系统, 因此全局的pool存储的都是一些静态的不会变动的数据, 而会变动的数据都会单独创建一个pool, 用完之后释放掉pool, 也就实现了集中申请集中释放, 肯定会有浪费内存的现象存在, 和提高运行速度比起来, 浪费点内存还是可以接受的.
分配原生大小内存, 一般字符串, 一整块内存的时候使用.
关于大块内存申请是直接向系统申请, 释放的时候直接返回给系统, 没有什么好讲的.
基本数据结构
typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t; typedef struct ngx_pool_large_s ngx_pool_large_t; typedef struct ngx_pool_s ngx_pool_t; struct ngx_pool_cleanup_s { ngx_pool_cleanup_pt handler; void *data; ngx_pool_cleanup_t *next; }; struct ngx_pool_large_s { ngx_pool_large_t *next; void *alloc; }; typedef struct { /*使用的内存位置*/ u_char *last; /*分配总的内存结束位置*/ u_char *end; /*下一块内存指针*/ ngx_pool_t *next; /*标记分配失败次数*/ ngx_uint_t failed; } ngx_pool_data_t; struct ngx_pool_s { /*内存池中内存空间*/ ngx_pool_data_t d; /*最大内存限定*/ size_t max; /*当前内存池分配内存位置*/ ngx_pool_t *current; /*缓存chain链表, 重新申请时从这里直接取出*/ ngx_chain_t *chain; /*大块内存链表, 很简单直接分配内存, 挂接到链表结束为止*/ ngx_pool_large_t *large; ngx_pool_cleanup_t *cleanup; ngx_log_t *log; };
创建内存池
创建一块内存池, 首先会申请一块用户指定的大小, 即size大小, 但是size很显然最小要为sizeof(ngx_pool_t)大小, 申请内存开头放置ngx_pool_t结构体, 剩余的用作内存池内存, 提供给用户使用, 如下图示|----------------> size <--------------------| |-----------------|--------------------------| p ngx_pool_t p->d.last p->d.end
ngx_pool_t * ngx_create_pool(size_t size, ngx_log_t *log) { ngx_pool_t *p; /*申请size大小内存*/ p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log); if (p == NULL) { return NULL; } /*用户使用内存要除去sizeof(ngx_pool_t)大小*/ 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; /*设置当前使用的pool为p,因为就一个*/ p->current = p; p->chain = NULL; p->large = NULL; p->cleanup = NULL; p->log = log; return p; }
申请内存
分配带内存对齐的内存, 一般用于结构体, 加快访问速度.void * ngx_palloc(ngx_pool_t *pool, size_t size) { u_char *m; ngx_pool_t *p; /*size大小决定进行小块内存分配还是大块内存分配方案*/ if (size <= pool->max) { /*取出当前pool*/ p = pool->current; do { m = ngx_align_ptr(p->d.last, NGX_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_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; 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); }
重新分配一个pool
static void * ngx_palloc_block(ngx_pool_t *pool, size_t size) { u_char *m; size_t psize; ngx_pool_t *p, *new, *current; /*内存大小和第一次用户指定的大小一致*/ psize = (size_t) (pool->d.end - (u_char *) pool); m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); if (m == NULL) { return NULL; } new = (ngx_pool_t *) m; new->d.end = m + psize; new->d.next = NULL; new->d.failed = 0; /*由于只使用了ngx_pool_data_t数据结构, 因此这里实际可使用的内存只去除了sizeof(ngx_pool_data_t)大小, 跟创建时sizeof(ngx_pool_t)不同*/ m += sizeof(ngx_pool_data_t); m = ngx_align_ptr(m, NGX_ALIGNMENT); new->d.last = m + size; current = pool->current; /*遍历链表最后位置, 但current并不一定到最后, current从分配失败次数少于三次位置开始, 目的是减少分配时遍历的次数*/ for (p = current; p->d.next; p = p->d.next) { if (p->d.failed++ > 4) { current = p->d.next; } } /*最新分配的内存放置到链表末尾*/ p->d.next = new; pool->current = current ? current : new; return m; }
关于大块内存申请是直接向系统申请, 释放的时候直接返回给系统, 没有什么好讲的.
相关文章推荐
- NGINX(一)内存结构
- nginx优化
- Nginx隐藏版本号
- nginx的真实IP
- nginx的log配置
- 上传文件被nginx全部缓存的问题
- ubuntu下使用apt方式安装、卸载nginx
- nginx、fastCGI、php-fpm关系梳理(转)
- CentOS 下安装Nginx
- nginx 安装sticky遇到的问题
- 搭建Nginx+Java环境
- Nginx/LVS/HAProxy负载均衡软件的优缺点详解
- Nginx 四种分配方式
- Nginx基本配置、性能优化指南
- 用nginx图片缓存服务器
- nginx重新加载配置
- Nginx介绍及企业web服务软件选择
- nginx配置location总结及rewrite规则写法
- nginx location匹配规则
- nginx配置详解、端口重定向和504