当前位置: 首页 > 后端技术 > PHP

swoole的memory全局内存池分析

时间:2023-03-30 00:55:18 PHP

内存池的作用:直接使用系统调用malloc会有以下缺点:频繁分配内存会产生大量内存碎片频繁分配内存会增加系统调用的开销,容易造成内存泄漏内存池是预申请一定数量的大小相等的内存块作为Readytouse;需要的时候分配一部分内存给内存池,如果内存块不够用,就向系统申请新的内存块。下面以swoole的swMemoryGlobal内存池为例进行分析。swooleswMemoryPool数据结构设计swMemoryGlobal是swoole内存池的实现方式之一,学习内存池主要是掌握其数据结构的设计,memoryGlobal的实现如下://src/memory/MemoryGlobal.ctypedefstruct_swMemoryPool{void*object;//指向swMemoryGlobal的指针void*(*alloc)(struct_swMemoryPool*pool,uint32_tsize);//分配内存函数指针void(*free)(struct_swMemoryPool*pool,void*ptr);//内存函数指针void(*destroy)(struct_swMemoryPool*pool);//销毁内存函数指针}swMemoryPool;typedefstruct_swMemoryGlobal{uint8_tshared;uint32_t页面大小;//指定每个swMemoryGlobal_page需要申请内存大小swLock锁;//互斥swMemoryGlobal_page*root_page;//指向第一个swMemoryGlobal_page指针,带头指针可以破坏内存池swMemoryGlobal_page*current_page;//指向当前swMemoryGlobal_page指针uint32_tcurrent_offset;}swMemoryGlobal;typedefstruct_swMemoryGlobal_page{struct_swMemoryGlobal_page*next;//指向下一个节点charmemory[0];//这是一个灵活的数组,用于记录申请内存后的内存地址}swMemoryGlobal_page;这三者的关系如下:swMemoryPoolswMemoryPool可以看成是一个类,它提到了alloc,free,destroy方法,还有object的属性,object其实是指向swMemoryGlobal的指针,而alloc,free,destroy是对它的操作object,即通过alloc,free,destroy来操作swMemoryGlobal上的内容,例如://src/core/base.c//initglobalsharedmemorySwooleG.memory_pool=swMemoryGlobal_new(SW_GLOBAL_MEMORY_PAGESIZE,1);SwooleGS=SwooleG.memory_pool->alloc(SwooleG.memory_pool,sizeof(SwooleGS_t));上面代码是分配sizeof(SwooleGS_t)大小的内存swMemoryGlobalswMemoryGlobal维护一个链表,每个节点是swMemoryGlobal_page,root_page指向第一个节点,current_page指向当前节点,pagesize指的是为某个节点申请的内存大小,current_offset表示一个节点已经使用内存swMemoryGlobal_pageswoole根据swMemoryGlobal.pagesize申请指定大小的内存,如下://src/memory/MemoryGlobal.cswMemoryGlobal_page*page=swMemoryGlobal_new_page(&通用汽车);上面说了swMemoryGlobal_page是一个链表节点。这里需要说明的是第一个节点。第一个节点的current_offset为sizeof(swMemoryGlobal)+sizeof(swMemoryPool);它不是0;以下代码,当第一个swMemoryGlobal_page申请内存后,立即为swMemoryPool和swMemoryGlobal分配内存//src/memory/MemoryGlobal.cgm.pagesize=pagesize;//系统申请一个pagesize内存swMemoryGlobal_page*page=swMemoryGlobal_new_page(&gm);if(page==NULL){returnNULL;}if(swMutex_create(&gm.lock,shared)<0){returnNULL;}gm.root_page=page;//page->内存为空闲内存gm_ptr=(swMemoryGlobal*)page->memory;gm.current_offset+=sizeof(swMemoryGlobal);//swMemoryPool指向空闲内存偏移地址,占用sizeof(swMemoryPool)内存swMemoryPool*allocator=(swMemoryPool*)(page->memory+gm.current_offset);通用汽车。current_offset+=sizeof(swMemoryPool);分配器->对象=gm_ptr;分配器->alloc=swMemoryGlobal_alloc;分配器->销毁=swMemoryGlobal_destroy;allocator->free=swMemoryGlobal_free;//将gm写入gm_ptr,即空闲内存(gm)前的sizeofforswMemoryGlobalmemcpy(gm_ptr,&通用汽车,sizeof(通用汽车));内存分配由swMemoryGlobal_alloc方法执行;这个方法是swMemoryPool的一个函数指针,如下allocator->alloc=swMemoryGlobal_alloc;//分配方法//src/core/base.c//初始化全局共享内存SwooleG.memory_pool=swMemoryGlobal_new(SW_GLOBAL_MEMORY_PAGESIZE,1);SwooleGS=SwooleG.memory_pool->alloc(SwooleG.memory_pool,sizeof(SwooleGS_t));//src/memory/MemoryGlobal.cstaticvoid*swMemoryGlobal_alloc(swMemoryPool*pool,uint32_tsize){swMemoryGlobal*gm=pool->object;gm->lock.lock(&gm->lock);if(size>gm->pagesize-sizeof(swMemoryGlobal_page))//sizeof(swMemoryGlobal_page)是类型swMemoryGlobal_pagepointersize{swWarn("无法分配%d字节,超过最大大小[%d]。",size,gm->pagesize-(int)sizeof(swMemoryGlobal_page));gm->lock.unlock(&gm->锁);返回空值;}//如果一个节点不够分配内存,重新申请一个新节点,将当前节点current_page设置为新节点if(gm->current_offset+size>gm->pagesize-sizeof(swMemoryGlobal_page)){swMemoryGlobal_page*page=swMemoryGlobal_new_page(gm);if(page==NULL){swWarn("swMemoryGlobal_alloc分配内存错误。");gm->lock.unlock(&gm->lock);返回空值;}gm->current_page=page;}void*mem=gm->current_page->memory+gm->current_offset;gm->current_offset+=大小;gm->lock.unlock(&gm->lock);//result返回空闲内存的偏移地址returnmem;}flexiblearrayflexiblearray(0-lengtharray)功能:为了满足变长结构的需要(structuresarevariable-length),数组名不占用空间,分配的内存是连续的,不会像定长数组那样浪费空间。它不会像指针那样需要单独分配内存,单独释放内存。定长数组使用起来方便,但是比较浪费空间。指针形式只多用了一个指针空间,不会导致我的NotesFlexibleArrayReference

最新推荐
猜你喜欢