当前位置: 首页 > wzjs >正文

猎头公司注册条件长沙seo顾问

猎头公司注册条件,长沙seo顾问,建设常规的网站报价是多少,徐州做网站的目录 内存池的介绍 与malloc/free相比 1.分配效率 2.内存碎片 3.使用场景 内存管理组件 1.jemalloc 2.tcmalloc 内存管理 定长 1.内存池初始化 2.内存分配 3.内存释放 不定长 1.内存池结构 2.内存分配 3.内存释放 内存池的介绍 1.预先分配内存:内存池是在…

目录

内存池的介绍

与malloc/free相比

        1.分配效率

        2.内存碎片

        3.使用场景

内存管理组件

        1.jemalloc

        2.tcmalloc

内存管理        

        定长

        1.内存池初始化

        2.内存分配

        3.内存释放

      不定长

        1.内存池结构

        2.内存分配

        3.内存释放


内存池的介绍

        1.预先分配内存:内存池是在程序运行初期,预先从系统申请一块较大连续内存空间的池式结构。

        2.管理内存分配与回收:负责管理内存空间的分配与回收工作,当程序需要小块内存时,直接从内存池中取出合适的部分交付,而不是频繁向系统请求;当程序释放内存时,内存池将其回收,等待下次再分配,而非立刻归还给系统。

        3.提高效率与减少内存碎片:减少因频繁系统调用带来的开销,提高内存分配的效率。同时降低内存碎片的产生,因为系统调用分配内存相对耗时,且零散的内存分配易产生碎片,内存池通过集中管理内存,有效解决了这些问题。

        4.定制化内存管理:内存池可根据不同场景和需求,定制内存分配策略,以满足特定程序对内存的独特要求。

与malloc/free相比

        1.分配效率

        内存池:在程序启动时预先从操作系统申请一大块内存。后续程序需要内存时,直接从内存池中分配,无需再进行系统调用,大大减少了时间开销,显著提升了内存分配的效率。

        malloc/free:是 C 语言标准库提供的内存分配与释放函数。每次调用malloc时,它会向操作系统发起内存分配请求,这涉及用户态到内核态的切换,需要一定的时间开销。尤其在频繁分配小块内存的场景下,这种开销会不断累积,严重影响程序运行效率。

        2.内存碎片

        内存池:通过对预先申请的大块内存进行管理,能有效减少内存碎片。它可以采用特定的数据结构和算法,将内存分割成大小固定或按一定规则的小块进行分配。当小块内存被释放时,内存池能方便地将其重新整合,避免了内存碎片化问题,使内存空间始终保持较高的利用率。

        malloc/free:频繁的内存分配和释放极易产生内存碎片。当程序分配不同大小的内存块后又释放部分块时,内存空间会变得零散。

        外部碎片:表现为内存中存在许多分散的、不连续的小空闲区域,这些空闲区域分布在已分配的内存块之间

        内部碎片:表现为每个已分配的内存块内部存在未被利用的空闲部分,它是隐藏在已分配内存块内部的

        3.使用场景

        内存池:适合对内存分配效率和内存管理要求较高的场景。

        malloc/free:适用于内存分配需求较为简单、内存使用量不大且对性能要求不是特别苛刻的场景。

内存管理组件

        1.jemalloc

        设计理念:设计理念是通用性和可扩展性。它不仅考虑了内存分配的性能,还注重对内存碎片的管理。

        内存管理策略

                多级分配:将内存划分为不同的大小类别,每个类别有独立的分配器。

                内存碎片管理:采用了先进的算法来减少内存碎片。它会尝试将空闲内存块合并,以提供更大的连续内存空间。

        使用场景:适用于对内存碎片敏感、需要处理各种大小内存分配的应用程序。

        2.tcmalloc

        设计理念:更侧重于为多线程应用程序提供高性能的内存分配。

        内存管理策略:

                线程本地缓存:每个线程都有自己的本地缓存,当线程需要分配内存时,首先会在本地缓存中查找可用的内存块,避免了线程之间的锁竞争。

                中央自由列表:用于管理全局的空闲内存块。当线程的本地缓存满了或者需要释放内存时,会将内存块放回中央自由列表。

        使用场景:更适合多线程应用程序,特别是那些对内存分配速度要求较高的场景。

内存管理        

        定长
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 定义内存页的大小为 4096 字节
#define MEM_PAGE_SIZE	0x1000  // 定义内存池结构体
typedef struct mempool_s {// 每个内存块的大小int blocksize;// 空闲内存块的数量int freecount;// 指向空闲内存块链表的头指针char *free_ptr;// 指向内存池的起始地址char *mem;
} mempool_t; // 创建内存池
// 参数: m 为指向内存池结构体的指针, block_size 为每个内存块的大小
// 返回值: 成功返回 0, 失败返回 -1 或 -2
int memp_create(mempool_t *m, int block_size) {// 检查指针是否为空if (!m) return -1;// 设置每个内存块的大小m->blocksize = block_size;// 计算空闲内存块的数量m->freecount = MEM_PAGE_SIZE / block_size;// 分配内存页m->mem = (char *)malloc(MEM_PAGE_SIZE); // 检查内存分配是否成功if (!m->mem) { return -2;}// 将分配的内存页初始化为 0memset(m->mem, 0, MEM_PAGE_SIZE); // 空闲内存块链表的头指针指向内存池的起始地址m->free_ptr = m->mem;int i = 0;char *ptr = m->mem;// 构建空闲内存块链表for (i = 0; i < m->freecount; i++) {// 将当前内存块的下一个指针指向下一个内存块的地址*(char **)ptr = ptr + block_size;// 移动指针到下一个内存块ptr = ptr + block_size;} // 最后一个内存块的下一个指针置为 NULL*(char **)ptr = NULL;return 0;
}// 销毁内存池
// 参数: m 为指向内存池结构体的指针
void memp_destory(mempool_t *m) {// 检查指针是否为空if (!m) return;// 释放内存池分配的内存free(m->mem);
}// 从内存池中分配一个内存块
// 参数: m 为指向内存池结构体的指针
// 返回值: 成功返回分配的内存块的指针, 失败返回 NULL
void *memp_alloc(mempool_t *m) {// 检查指针是否为空或没有空闲内存块if (!m || m->freecount == 0) return NULL;// 获取当前空闲内存块链表的头指针void *ptr = m->free_ptr;// 更新空闲内存块链表的头指针为下一个空闲内存块m->free_ptr = *(char **)ptr;// 空闲内存块数量减 1m->freecount--;return ptr;
}// 将内存块释放回内存池
// 参数: m 为指向内存池结构体的指针, ptr 为要释放的内存块的指针
void memp_free(mempool_t *m, void *ptr) {// 将释放的内存块插入到空闲内存块链表的头部*(char **)ptr = m->free_ptr;// 更新空闲内存块链表的头指针为释放的内存块m->free_ptr = (char *)ptr;// 空闲内存块数量加 1m->freecount++;
}// 主函数, 用于测试内存池的功能
int main() {// 定义一个内存池结构体变量mempool_t m;// 创建内存池, 每个内存块大小为 32 字节memp_create(&m, 32);// 从内存池中分配一个内存块void *p1 = memp_alloc(&m);printf("memp_alloc : %p\n", p1);// 从内存池中分配一个内存块void *p2 = memp_alloc(&m);printf("memp_alloc : %p\n", p2);// 从内存池中分配一个内存块void *p3 = memp_alloc(&m);printf("memp_alloc : %p\n", p3);// 将内存块 p2 释放回内存池memp_free(&m, p2);return 0;
}

定长分配是一种内存管理策略,它将一块连续的内存空间划分为多个固定大小的内存块。

        1.内存池初始化

        在memp_create函数中,会分配一块大小为MEM_PAGE_SIZE的连续内存空间作为内存池。然后,根据指定的block_size将内存池划分为多个固定大小的内存块,并通过链表的方式将这些空闲内存块连接起来。

        2.内存分配

        在memp_alloc函数中,当需要分配内存时,会从空闲内存块链表的头部取出一个内存块,并将空闲内存块链表的头指针指向下一个空闲内存块。同时,空闲内存块的数量减 1。

        3.内存释放

        在memp_free函数中,当需要释放内存时,会将释放的内存块插入到空闲内存块链表的头部,并更新空闲内存块链表的头指针。同时,空闲内存块的数量加 1。

定长分配可以有效地减少内存碎片的产生,提高内存分配和释放的效率。因为每个内存块的大小是固定的,所以在分配和释放内存时不需要进行复杂的内存管理操作,只需要简单地操作链表即可。

      不定长
// 定义内存池节点结构体
typedef struct mp_node_s {// 指向当前节点未使用内存的起始位置unsigned char *last;// 指向当前节点内存的结束位置unsigned char *end;// 指向下一个内存池节点的指针struct mp_node_s *next;
} mp_node_t;// 定义大内存块结构体
typedef struct mp_large_s {// 指向下一个大内存块的指针struct mp_large_s *next;// 指向实际分配的大内存块的指针void *alloc;
} mp_large_t;// 定义内存池结构体
typedef struct mp_pool_s {// 内存池节点可分配的最大内存块大小size_t max; // 指向内存池节点链表的头节点struct mp_node_s *head;// 指向大内存块链表的头节点struct mp_large_s *large;
} mp_pool_t;// 创建内存池的函数声明
int mp_create(mp_pool_t *pool, size_t size);
// 销毁内存池的函数声明
void mp_destory(mp_pool_t *pool);
// 从内存池分配内存的函数声明
void *mp_alloc(mp_pool_t *pool, size_t size);
// 释放内存池内存的函数声明
void mp_free(mp_pool_t *pool, void *ptr);// 创建内存池
// 参数 pool 为指向内存池结构体的指针,size 为内存池节点的初始大小
// 返回值:成功返回 0,失败返回 -1
int mp_create(mp_pool_t *pool, size_t size) {// 检查指针是否为空或者请求的大小是否合法if (!pool || size <= 0) return -1;// 分配一块指定大小的内存void *mem = malloc(size);// 将这块内存的起始部分作为一个内存池节点struct mp_node_s *node = (struct mp_node_s *)mem;// 计算该节点中可用于分配的内存起始位置node->last = (char *)mem + sizeof(struct mp_node_s);// 计算该节点的内存结束位置node->end = (char *)mem + size;// 该节点目前没有下一个节点node->next = NULL;// 内存池的头节点指向该节点pool->head = node;// 设置内存池节点可分配的最大内存块大小pool->max = size;// 初始时没有大内存块pool->large = NULL;return 0;
}// 销毁内存池
// 参数 pool 为指向内存池结构体的指针
void mp_destory(mp_pool_t *pool) {mp_large_t *l;// 遍历大内存块链表for (l = pool->large; l; l = l->next) {// 如果该大内存块有实际分配的内存if (l->alloc) {// 释放该大内存块free(l->alloc);}}// 清空大内存块链表pool->large = NULL;// 指向内存池节点链表的头节点mp_node_t *node = pool->head;// 修正原代码中判断条件错误,这里应该是 node 不为空while (node) {// 保存下一个节点的指针mp_node_t *tmp = node->next;// 释放当前节点free(node);// 移动到下一个节点node = tmp;}
}// 从内存池分配一个新的节点块
// 参数 pool 为指向内存池结构体的指针,size 为需要分配的内存大小
// 返回值:分配成功返回指向分配内存的指针,失败情况未处理完整
static void *mp_alloc_block(mp_pool_t *pool, size_t size) {// 原代码此处 mem 未定义,应修改为 malloc 分配内存void *mem = malloc(pool->max);struct mp_node_s *node = (struct mp_node_s *)mem;// 计算该节点中可用于分配的内存起始位置node->last = (char *)mem + sizeof(struct mp_node_s);// 计算该节点的内存结束位置node->end = (char *)mem + pool->max;// 该节点目前没有下一个节点node->next = NULL;// 获取当前可分配的内存起始位置void *ptr = node->last;// 更新可分配内存的起始位置node->last += size;// 找到内存池节点链表的尾节点mp_node_t *iter = pool->head;while (iter->next != NULL) {iter = iter->next;}// 将新节点插入到链表尾部iter->next = node;return ptr;
}// 从内存池分配大内存块
// 参数 pool 为指向内存池结构体的指针,size 为需要分配的大内存块大小
// 返回值:分配成功返回指向分配内存的指针,失败返回 NULL
static void *mp_alloc_large(mp_pool_t *pool, size_t size) {// 检查指针是否为空if (!pool) return NULL;// 直接调用系统的 malloc 分配大内存块void *ptr = malloc(size);// 检查是否分配成功if (ptr == NULL) return NULL;mp_large_t *l;// 遍历大内存块链表,查找是否有未使用的节点for (l = pool->large; l; l = l->next) {if (l->alloc == NULL) {// 如果找到未使用的节点,将其指向新分配的大内存块l->alloc = ptr;return ptr;}}// 如果没有找到未使用的节点,从内存池分配一个大内存块结构体l = (mp_large_t *)mp_alloc(pool, sizeof(mp_large_t));if (l == NULL) {// 如果分配失败,释放之前分配的大内存块free(ptr);return NULL;}// 将新分配的大内存块结构体指向实际的大内存块l->alloc = ptr;// 将新的大内存块结构体插入到大内存块链表头部l->next = pool->large;pool->large = l;return ptr;
}// 从内存池分配内存
// 参数 pool 为指向内存池结构体的指针,size 为需要分配的内存大小
// 返回值:分配成功返回指向分配内存的指针,失败返回 NULL
void *mp_alloc(mp_pool_t *pool, size_t size) {// 如果请求的内存大小超过内存池节点可分配的最大大小if (size > pool->max) {// 调用分配大内存块的函数return mp_alloc_large(pool, size);} // 请求的内存大小小于等于内存池节点可分配的最大大小void *ptr = NULL;// 指向内存池节点链表的头节点mp_node_t *node = pool->head;do {// 检查当前节点是否有足够的空间if (node->end - node->last > size) {// 获取当前可分配的内存起始位置ptr = node->last;// 更新可分配内存的起始位置node->last += size;return ptr;} // 移动到下一个节点node = node->next;} while (node);// 如果所有节点都没有足够的空间,分配一个新的节点块return mp_alloc_block(pool, size);
}// 释放内存池中的内存
// 参数 pool 为指向内存池结构体的指针,ptr 为要释放的内存指针
void mp_free(mp_pool_t *pool, void *ptr) {mp_large_t *l;// 遍历大内存块链表for (l = pool->large; l; l = l->next) {// 如果找到要释放的大内存块if (l->alloc == ptr) {// 释放该大内存块free(l->alloc);// 将该大内存块结构体的 alloc 指针置为 NULLl->alloc = NULL;return;}}// 对于小内存块,这里未做具体释放操作,因为小内存块是按节点整体管理
}

 核心思想是将内存分配分为小内存块和大内存块两种情况分别处理,以提高内存分配和释放的效率,减少内存碎片。

        1.内存池结构

            mp_pool_t:这是内存池的核心结构体,包含三个重要成员

                        max:表示内存池节点可分配的最大内存大小

                        head:指向内存池节点链表的头节点,这些节点用于分配小内存块

                        large:指向大内存块链表的头节点,用于管理超过max大小的大内存块

          mp_node_t:小内存块结构体,用于管理小内存块,last指针指向当前节点未使用内存的起始位置,end指针指向当前节点内存的结束位置,next指针指向下一个节点。

          mp_large_t:大内存块结构体,alloc指针指向实际分配的大内存块,next指针指向下一个大内存块。

        2.内存分配

        小内存块分配:当请求的内存大小size小于等于pool->max时,会遍历内存池节点链表,检查每个节点是否有足够的空间。如果有,则从该节点分配内存并更新last指针;如果所有节点都没有足够的空间,则调用mp_alloc_block函数分配一个新的节点块。

        大内存块分配:当请求的内存大小size大于pool->max时,直接调用系统的malloc函数分配大内存块。然后会先遍历大内存块链表,查找是否有未使用的节点,如果有则将其指向新分配的大内存块;如果没有,则从内存池分配一个大内存块结构体,并将其插入到大内存块链表头部。

        3.内存释放

        大内存块释放:当调用mp_free函数释放内存时,会先遍历大内存块链表,找到要释放的大内存块,然后调用free函数释放该大内存块,并将该大内存块结构体的alloc指针置为 NULL。

        小内存块释放:小内存块是按节点整体管理的,在销毁内存池时会统一释放所有节点的内存。

使用不定长内存池可以高效地处理不同大小的内存分配请求,同时减少了频繁调用系统mallocfree带来的开销和内存碎片问题。

http://www.dtcms.com/wzjs/147573.html

相关文章:

  • 仙桃有哪些做网站的公司网络营销主要是什么
  • 单位网站建设内容东莞今天发生的重大新闻
  • 网站建设方面的销售经验深圳关键词排名优化系统
  • centos 7.2 做网站广告开户
  • 北京市住房和城乡建设部网站官网网络优化工程师
  • 建立网站陕西网站制作
  • 怎么做返利网站软文编辑
  • 山西公司响应式网站建设平台软文是什么
  • 股票网站怎么做动态表格百度查询入口
  • 做flash音乐网站的开题报告赣州seo排名
  • 做网站ps切图上海网站关键词排名优化报价
  • 做爰小视频网站网站如何进行seo
  • 文化传媒可以做网站吗体育热点新闻
  • 哪里有网站建设流程广州seo排名收费
  • 京东的网站建设介绍站长工具中文
  • 网站怎么做图片动态图片大全万能搜索
  • 2022中央农村工作会议公报网站推广优化c重庆
  • 怎么做网站优化 sit临沂seo优化
  • 手机端网站设计制作案例南京百度推广优化
  • www开头网站怎么做百度服务商
  • wordpress getuser广州排前三的seo公司
  • 徐州哪里做网站好互联网创业项目
  • 卓辉科技 网站建设中层管理者培训课程有哪些
  • 局域网内部网站建设app商品推广软文写作500字
  • 音乐分享网站开发2024年度关键词
  • 备案主体负责人 网站负责人廊坊百度快照优化哪家服务好
  • 网站站长 感受写软文推广
  • 免费设计海报网站bt最佳磁力搜索引擎
  • 网站制作百度友情链接交易平台
  • 米拓建站怎么样企业网站制作开发