linux高性能服务器--Ngix内存池简单实现

news/2024/9/23 0:31:12/

文章目录

      • 内存模型:
      • 流程图
      • 内存对齐
      • code

内存模型:

在这里插入图片描述

流程图

在这里插入图片描述

内存对齐

对齐计算
要分配一个以指定大小对齐的内存,可以使用如下公式:
假设要分配大小为n,对齐方式为x,那么 size=(n+(x-1)) & (~(x-1))。
举个例子:
n=17,x=4。即申请大小为17,对齐为4。则计算出对齐后的大小应该为
(17+4-1)&(~(4-1))=20;

code

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>#include <fcntl.h>#define MP_ALIGNMENT       		32
#define MP_PAGE_SIZE			4096
#define MP_MAX_ALLOC_FROM_POOL	(MP_PAGE_SIZE-1)// 对齐
#define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
#define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))typedef struct mp_large_s {struct mp_large_s *next;void *alloc;}mp_large_t;typedef struct mp_node_s {unsigned char *last; // last之前为已使用的内存unsigned char *end; // last到end之间为可分配内存struct mp_node_s *next;size_t failed;
}mp_node_t;typedef struct mp_pool_s {size_t max;mp_node_t* current;mp_large_t* large;mp_node_t head[0];}mp_pool_t;mp_pool_t *mp_create_pool(size_t size)
{mp_pool_t *p;// malloc无法分配超过4k的内存,size + sizeof(mp_pool_t) + sizeof(mp_node_s)保证有size大小可用int ret = posix_memalign((void*)&p, MP_ALIGNMENT, size + sizeof(mp_pool_t) + sizeof(mp_node_t));if (ret)return NULL;p->max = size;p->current = p->head;p->large = NULL;//(unsigned char*)(p + 1)// (unsigned char*)p + sizeof(mp_pool_t)p->head->last = (unsigned char*)p + sizeof(mp_pool_t)+sizeof(mp_node_t);p->head->end = p->head->last + size;p->head->failed = 0;return p;
}
void mp_destory_pool(mp_pool_t *pool) 
{mp_node_t *h, *n;mp_large_t *l;for (l = pool->large; l; l = l->next) {if (l->alloc) {free(l->alloc);}}h = pool->head->next;while (h) {n = h->next;free(h);h = n;}free(pool);
}void *mp_alloc_small(mp_pool_t *pool, size_t size)
{unsigned char *m;struct mp_node_s *h = pool->head;size_t psize = (size_t)(h->end - (unsigned char *)h);int ret = posix_memalign((void*)&m, MP_ALIGNMENT, psize);if (ret)return NULL;mp_node_t *p, *new_node, *current;new_node = (mp_node_t *)m;new_node->next = NULL;new_node->end = m + psize;new_node->failed = 0;m += sizeof(mp_node_t);m = mp_align_ptr(m, MP_ALIGNMENT);new_node->last += size;current = pool->current;for (p = current; p->next; p = p->next){// 如存在多次分配失败,current不再指向此nodeif (p->failed++ > 4){current = p->next;}}p->next = new_node;pool->current = current ? current : new_node;return m;
}static void *mp_alloc_large(mp_pool_t *pool, size_t size) 
{void *p = NULL;int ret = posix_memalign((void*)&p, MP_ALIGNMENT, size);if (ret)return NULL;mp_large_t *large;// 查找是否有已经释放的large,在large list里面找到一个 null的节点size_t n = 0;for (large = pool->large; large; large = large->next){if (large->alloc == NULL){large->alloc = p;return p;}// 避免遍历链条太长if (n++ > 3)break;}// 大内存块的头作为小块保存在small中large = mp_alloc_small(pool, sizeof(mp_large_t));// 头插法large->alloc = p;large->next = pool->large;pool->large = large;
}void *mp_malloc(mp_pool_t *pool, size_t size)
{if (size > pool->max)return mp_alloc_large(pool, size);mp_node_t *p = pool->current;while (p){if (p->end - p->last < size){p = p->next;continue;}unsigned char *m = mp_align_ptr(p->last, MP_ALIGNMENT);p->last = m + size;return m;}return mp_alloc_small(pool, size);
}void *mp_calloc(mp_pool_t *pool, size_t size) 
{void *p = mp_malloc(pool, size);if (p) {memset(p, 0, size);}return p;}
void mp_free(mp_pool_t *pool, void *p)
{mp_large_t *l;for (l = pool->large; l; l = l->next){if (p == l->alloc){free(l->alloc);l->alloc = NULL;return;}}
}void mp_reset_pool(mp_pool_t *pool) 
{mp_node_t *h;mp_large_t *l;for (l = pool->large; l; l = l->next) {if (l->alloc) {free(l->alloc);}}pool->large = NULL;for (h = pool->head; h; h = h->next) {h->last = (unsigned char *)h + sizeof(mp_node_t);}}/******************* TEST *********************/
int main(int argc, char *argv[]) {int size = 1 << 12;mp_pool_t *p = mp_create_pool(size);int i = 0;for (i = 0; i < 10; i++) {void *mp = mp_malloc(p, 512);//		mp_free(mp);}printf("mp_align(123, 32): %d, mp_align(17, 32): %d\n", mp_align(24, 32), mp_align(17, 32));int j = 0;for (i = 0; i < 5; i++) {char *pp = mp_calloc(p, 32);for (j = 0; j < 32; j++) {if (pp[j]) {printf("calloc wrong\n");}printf("calloc success\n");}}//printf("mp_reset_pool\n");for (i = 0; i < 5; i++) {void *l = mp_malloc(p, 8192);mp_free(p, l);}mp_reset_pool(p);//printf("mp_destory_pool\n");for (i = 0; i < 58; i++) {mp_malloc(p, 256);}mp_destory_pool(p);return 0;}

参考:
https://blog.csdn.net/Long_xu/article/details/126887578


http://www.ppmy.cn/news/1458825.html

相关文章

基于springboot+mybatis+vue的项目实战之增删改查CRUD

目录结构 PeotController.java package com.example.controller;import com.example.pojo.Peot; import com.example.pojo.Result; import com.example.service.PeotService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web…

网工内推 | 技术支持工程师,最高15k,加班有补贴

01 星网信通 招聘岗位&#xff1a;售前技术支持 职责描述&#xff1a; 1、售前技术支持&#xff1a;技术交流、产品选型报价、方案制作等工作&#xff1b; 2、招投标支持&#xff1a;项目招标参数撰写、标书质疑、应标文件技术部分撰写及资质文件归纳准备、现场讲标及技术澄清…

【触摸案例-手势解锁案例-按钮高亮 Objective-C语言】

一、我们来说这个self.btns,这个问题啊,为什么不用_btns, 1.我们说,在懒加载里边儿,经常是写下划线啊,_btns,为什么不写,首先啊,这个layoutSubviews:我们第一次,肯定会去执行这个layoutSubviews: 然后呢,去懒加载这个数组, 然后呢,接下来啊,走这一句话, 第一次…

Filter 和 HandlerInterceptor 的执行顺序

Filter 和 HandlerInterceptor 的执行顺序 在 Spring 框架中&#xff0c;Filter 和 HandlerInterceptor 的执行顺序如下&#xff1a; Filter&#xff08;过滤器&#xff09;&#xff1a; Filter 是 Java Servlet 规范中定义的组件&#xff0c;用于在请求进入 Servlet 之前或响应…

一起深度学习——CIFAR10

CIFAR10 目的&#xff1a;实现步骤&#xff1a;1、导包&#xff1a;2、下载数据集3、整理数据集4、将验证集从原始的训练集中拆分出来5、数据增强6、加载数据集7、定义训练模型&#xff1a;8、定义训练函数&#xff1a;9、定义参数&#xff0c;开始训练&#xff1a; 目的&#…

Baidu Comate智能编码助手

Baidu Comate智能编码助手 &#x1f388;1.Baidu Comate的简介&#x1f388;2.安装Baidu Comate&#x1f388;3.Baidu Comate实现功能&#x1f388;4.使用注释进行智能代码提示&#x1f388;5.结束语 &#x1f388;1.Baidu Comate的简介 根据官网的介绍&#xff0c;我们了解到B…

鸿蒙开发-ArkTS语言-容器-非线性容器

鸿蒙开发-UI-web 鸿蒙开发-UI-web-页面 鸿蒙开发-ArkTS语言-基础类库 鸿蒙开发-ArkTS语言-并发 鸿蒙开发-ArkTS语言-并发-案例 鸿蒙开发-ArkTS语言-容器 文章目录 前言 一、非线性容器 1.HashMap 2.HashSet 3.TreeMap 4.TreeSet 5.LightWeightMap 6.LightWeightSet 7.P…

多态的概念及运用

多态 概念&#xff1a;多态是指同一种行为具有多个不同的表现形式或形态的能力。在Java中&#xff0c;多态是指一个对象的实际类型可以是其父类或接口类型&#xff0c;但在运行时会根据其实际类型来调用相应的方法。是面向对象的第三大特征&#xff0c;建立于封装和继承之上。…