NGINX(二)内存池
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 之 内存池
1.基本结构 先来学习一下nginx内存池的几个主要数据结构:[见:./src/core/ngx_palloc.h/.c] ngx_pool_data_t(内存池数据块结构) 1: typed ...
- nginx 内存池分析
最近nginx的源码刚好研究到内存池,这儿就看下nginx内存池的相关的东西. 一,为什么要使用内存池 大多数的解释不外乎提升程序的处理性能及减小内存中的碎片,对于性能优化这点主要体现在: (1)系统 ...
- NGINX 内存池有感
写在前面 写NGINX系列的随笔,一来总结学到的东西,二来记录下疑惑的地方,在接下来的学习过程中去解决疑惑. 也希望同样对NGINX感兴趣的朋友能够解答我的疑惑,或者共同探讨研究. 整个NGINX系列 ...
- nginx源码学习----内存池
最近在进行监控平台的设计,之前一直觉得C/C++中最棘手的部分是内存的管理上,远不止new/delete.malloc/free这么简单.随着代码量的递增,程序结构复杂度的提高.各种内存方面的问题悄然 ...
- nginx源码分析—内存池结构ngx_pool_t及内存管理
Content 0. 序 1. 内存池结构 1.1 ngx_pool_t结构 1.2 其他相关结构 1.3 ngx_pool_t的逻辑结构 2. 内存池操作 2.1 创建内存池 2.2 销毁内存池 2 ...
- nginx源代码分析之内存池实现原理
建议看本文档时结合nginx源代码. 1.1 什么是内存池?为什么要引入内存池? 内存池实质上是接替OS进行内存管理.应用程序申请内存时不再与OS打交道.而是从内存池中申请内存或者释放内存到内存池 ...
- Nginx系列三 内存池的设计
Nginx的高性能的是用非常多细节来保证,epoll下的多路io异步通知.阶段细分化的异步事件驱动,那么在内存管理这一块也是用了非常大心血.上一篇我们讲到了slab分配器,我们能够能够看到那是对共享内 ...
- 菜鸟nginx源代码剖析数据结构篇(九) 内存池ngx_pool_t
菜鸟nginx源代码剖析数据结构篇(九) 内存池ngx_pool_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn ...
- 菜鸟nginx源码剖析数据结构篇(九) 内存池ngx_pool_t[转]
菜鸟nginx源码剖析数据结构篇(九) 内存池ngx_pool_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn. ...
随机推荐
- 省市选择(基于zepto.js)
效果如下: <div class="clList overflow-h mt75"> <select class="pull-left cl-35 se ...
- Class.forName、Class.class(属性)、getClass()的区别
1.出现的时期不同:Class.forName()在运行时加载:Class.class和getClass()是在编译器加载2.Class.class只是在编译时用来存放类的相关信息,并没有实例化对象: ...
- linux shell命令的常用快捷键
一些shell的常用快捷键. Ctrl + a 切换到命令行开始 Ctrl + e 切换到命令行末尾 Ctrl + l 清除屏幕内容 Ctrl + u 清除剪切光标之前的内容 Ctrl + ...
- UDP TCP应用场景
作者:陈硕链接:https://www.zhihu.com/question/20060141/answer/26735814来源:知乎著作权归作者所有,转载请联系作者获得授权. UDP 的使用范围很 ...
- Python的进程间通信
进程间通讯有多种方式,包括信号,管道,消息队列,信号量,共享内存,socket等 1.共享内存 Python可以通过mmap模块实现进程之间的共享内存 mmap文件对象既像一个字符串也像一个普通文件对 ...
- 开发设计模式(四) 代理模式(Proxy Pattern)
转自http://blog.sina.com.cn/s/blog_89d90b7c0101803g.html 代理模式:代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问.在某些情况下, ...
- 视图--bai
/*视图的必要性 create view population_all_view as select xxxx 详细信息 from qgck where rownum<500 -- sql语句不 ...
- cocos2dx android平台事件系统解析
对于cocos2dx在android平台事件的响应过程很模糊,于是分析了下源码,cocos2dx 版本3.4,先导入一个android工程,然后看下AndroidManifest.xml <ap ...
- 领域驱动设计和实践(转:http://kb.cnblogs.com/page/112298/)
引言 软件系统面向对象的设计思想可谓历史悠久,20世纪70年代的Smalltalk可以说是面向对象语言的经典,直到今天我们依然将这门语言视为面向对象语言的基础.随着编程语言和技术的发展,各种语言特性层 ...
- ElasticSearch入门-搜索如此简单
搜索引擎我也不是很熟悉,但是数据库还是比较了解.可以把搜索理解为数据库的like功能的替代品.因为like有以下几点不足: 第一.like的效率不行,在使用like时,一般都用不到索引,除非使用前缀匹 ...