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;
}

关于大块内存申请是直接向系统申请, 释放的时候直接返回给系统, 没有什么好讲的.

转载于:https://www.cnblogs.com/ourroad/p/4838362.html

NGINX(二)内存池相关推荐

  1. nginx的内存池及内存管理

    nginx对内存的管理是由自己实现的内存池结构ngx_pool_t来完成,本文主要讲nginx的内存管理. nginx对内存管理涉及到四个文件:src/core/ngx_palloc.h.src/co ...

  2. Nginx源码分析-内存池

    本文转自淘宝平台http://www.tbdata.org/archives/1390,不是为了夺他人之美,只是觉得写得很好,怕淘宝万一删掉就找不到了,放在这里保存一下.大家可以直接链接过去,他们那个 ...

  3. 这是我见过最详细的Nginx 内存池分析

    一,为什么要使用内存池 大多数的解释不外乎提升程序的处理性能及减小内存中的碎片,对于性能优化这点主要体现在: (1)系统的malloc/free等内存申请函数涉及到较多的处理,如申请时合适空间的查找, ...

  4. Nginx源码分析:核心数据结构ngx_cycle_t与内存池概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 核心数据结构与内存池概述 在Nginx中的核心数据结构就是ngx_cycle_t结构,在初始 ...

  5. nginx内存占用高---内存池使用思考

    nginx内存占用高-内存池使用思考 问题现象 nginx top 进程 虚拟内存 200G 实际内存5G 和 CDN 平台相比要高很多 排查思路 使用pmap -p 进程号,发现从系统角度确实 有分 ...

  6. nginx源码分析—内存池结构ngx_pool_t及内存管理

    本博客( http://blog.csdn.net/livelylittlefish)贴出作者(阿波)相关研究.学习内容所做的笔记,欢迎广大朋友指正! Content 0.序 1.内存池结构 1.1 ...

  7. 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.3重置内存 ...

  8. nginx源码分析之内存池实现原理

    建议看本文档时结合nginx源码: 1.1   什么是内存池?为什么要引入内存池? 内存池实质上是接替OS进行内存管理,应用程序申请内存时不再与OS打交道,而是从内存池中申请内存或者释放内存到内存池, ...

  9. Nginx源码阅读笔记-内存池的设计

    2019独角兽企业重金招聘Python工程师标准>>> nginx的内存池设计的比较简单了,一个内存池中分为两个部分: 超过max大小的内存分配,走大块内存分配,这部分内存管理由ng ...

  10. 【Nginx 源码学习】内存池 及 优秀案例赏析:Nginx内存池设计

    文章目录 关于设计内存池之我的想法 内存池案例 malloc 底层原理 jemalloc && tcmalloc Nginx内存池设计 基础数据结构 源码分析 ngx_create_p ...

最新文章

  1. linux删除zlib无法远程,linux zlib默认装在哪里
  2. Python-OpenCV 杂项(二)(三): 鼠标事件、 程序性能的检测和优化
  3. dede服务器建站_建站就是这么简单(内容系统管理CMS篇)
  4. Java多线程 - 线程组
  5. 《转》VC++多线程编程
  6. 机器人炒饭小块头一一_一罐好饭,智能机器人炒饭出好味道,小块头坚守本心匠心制作!...
  7. 基于PHP的Google Voice 短信API
  8. 港股区块链板块持续上行,火币科技涨超50%
  9. Zabbix 服务器性能指标参考(学习笔记十七)
  10. vim编辑python_Python3基础知识——Vi/Vim编辑器的使用,大神们都在用的
  11. 23种设计模式(九)对象创建之原型模式
  12. Linux系统管理初步(六)设置计划任务
  13. 单片机技术及应用:基于proteus仿真的c语言程序设计,单片机的C语言程序设计与应用:基于Proteus仿真(第4版)...
  14. 龙卷风袭击广东致6死215伤 广州停
  15. MySQL实现跨库join查询
  16. python如何制作地图热力图
  17. macbook重装系统 选择方案_超详细的mac重装系统教程
  18. Python小记(一):import和from。。。import区别?
  19. 查询Mysql版本号的两种方法
  20. 20届icoding 实验1

热门文章

  1. python调用C++
  2. doc转docx文件会乱吗_【转】帮你解决docx转换为doc文档的乱码问题
  3. 蓝桥杯2015年第六届C/C++省赛B组第一题-奖券数目
  4. CSS 实现盒子水平垂直居中
  5. Android Studio - xml布局文件不显示代码怎么办?
  6. Android-【报错】java.lang.ClassCastException: .MainActivity cannot be cast to java.lang.Runnable
  7. L1-012 计算指数 (5 分)—团体程序设计天梯赛
  8. C语言课程2——我们交流的工具:Coding.net
  9. Android中resource参数变量使用
  10. MySQL数据库(五)