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

【PHP7源码学习】2019-03-11PHP内存管理3笔记

时间:2023-03-29 14:51:09 PHP

baiyan所有视频:https://segmentfault.com/a/11...源视频地址:http://replay.xesv5.com/ll/24...回顾PHP内存分配过程使用gdb回顾PHP内存分配过程首先在_emalloc()函数处设置断点alloc_globals是一个全局变量,可以使用AG宏来访问内部字段接下来观察mm_heap中的字段:size=0,peak=0,表示当前没有使用内存real_size=2097152=2M,表示已经申请了一块内存给操作系统跟进main_chunk字段:内存的地址heap字段与上面mm_heap字段的地址相同,这样可以方便快捷的定位到chunk的mm_heap。注意它的地址是0x7ffff3800040,注意倒数第二位有一个4(十进制为64),也就是说它的起始地址不是正好2MB对齐,而是2MB+64B。为什么是这样?看下图,结构体的前几个字段刚好占据64B,所以heap_slot字段只能从64B的偏移位置开始。-next和prev字段表示双向链表中chunk和chunk之间的链接。当只有一个chunk节点时,next和prev指针都指向自己——free_pages字段为511,表示使用了512页中的一个,剩余511个空闲页——free_map字段为8个uint64_t类型,标记是否每页使用,一共512bit。每个chunk中的512页分为8组,每组64页,正好对应free_map中的每一项,0未使用,1已使用——map字段为512个uint32_t类型,共2KB。用来标记是小内存还是大内存,可以用低位来存储bit_num或者使用页数等信息。这里是大内存,已经使用了一页(存放在mm_heap中)。我们通过gdb,在_emalloc()之后,调用zend_mm_alloc_heap()函数,然后判断大小,这里小于3KB(ZEND_MM_MAX_SMALL_SIZE),所以这里调用了zend_mm_alloc_small()函数,zend_mm_alloc_small_slow()函数也可能被调用,视情况而定。然后计算bin_num,这里size为11,小于64。所以直接返回(size-!!size)>>3,打印结果为1。根据它的bin_num,去bin_data_size数组中找到那个应该分配的大小是16B。一页可分为256个16B,需要一页。这样PHP会取出1个16B返回给用户,剩下的255个16B会挂在free_slot链表上,数组下标为1(下标为0节省8B内存,而下标为1节省16B内存...),再次打印free_slot字段,观察第一个下标已经有元素,可以验证我们的结论。复杂的宏替换针对视频中的bin_data_size数组为什么最后被替换,以及为什么最后bin_data_size数组中只存入了data的size列的问题,为了说明方便,这里简化源码示例:#include#define_BIN_DATA_SIZE(num,size,elements,pages,x,y)大小,#defineZEND_MM_BINS_INFO(_,x,y)\_(0,8,512,1,x,y)\_(1,16,256,1,x,y)\_(2,24,170,1,x,y)\_(3,32,128,1,x,y)\_(4,40,102,1,x,y)\_(5,48,85,1,x,y)\_(6,56,73,1,x,y)\_(7,64,64,1,x,y)\_(8,80,51,1,x,y)\_(9,96,42,1,x,y)\_(10,112,36,1,x,y)\_(11,128,32,1,x,y)\_(12,160,25,1,x,y)\_(13,192,21,1,x,y)\_(14,224,18,1,x,y)\_(15,256,16,1,x,y)\_(16,320,64,5,x,y)\_(17,384,32,3,x,y)\_(18,448,9,1,x,y)\_(19,512,8,1,x,y)\_(20,640,32,5,x,y)\_(21,768,16,3,x,y)\_(22,896,9,2,x,y)\_(23,1024,8,2,x,y)\_(24,1280,16,5,x,y)\_(25,1536,8,3,x,y)\_(26,1792,16,7,x,y)\_(27,2048,8,4,x,y)\_(28,2560,8,5,x,y)\_(29,3072,4,3,x,y)intmain(){intbin_data_size[]={ZEND_MM_BINS_INFO(_BIN_DATA_SIZE,x,y)};for(inti=0;i#define_BIN_DATA_SIZE(num,size,elements,pages,x,y)size,#defineZEND_MM_BINS_INFO(_,x,y)_(0,8,512,1,x,y)intmain(){int数据[]={ZEND_MM_BINS_INFO(_BIN_DATA_SIZE,x,y)};for(inti=0;i

最新推荐
猜你喜欢