当前位置 : 主页 > 网络编程 > 其它编程 >

PHP内核探究内存管理与缓存机制

来源:互联网 收集:自由互联 发布时间:2023-07-02
前言PHP在运行时所需的内存是一次性向操作系统申请开辟的而不是分多次。那他是怎么样一次性申请呢机制又是如何 PHP在运行时所需的内存是一次性向操作系统申请开辟的而不是分多次
前言PHP在运行时所需的内存是一次性向操作系统申请开辟的而不是分多次。那他是怎么样一次性申请呢机制又是如何

PHP在运行时所需的内存是一次性向操作系统申请开辟的而不是分多次。那他是怎么样一次性申请呢机制又是如何请看下边介绍。

heap层是PHP内存管理的核心实现PHP底层对内存的管理 ZendMM向系统进行的内存申请并不是有需要时向系统即时申请 而是由ZendMM的最底层heap层先向系统申请一大块的内存 建立一个类似于内存池的管理机制unset后ZendMM并不会直接立刻将内存交回给系统而是只在自身维护的内存池(storge层)中将其重新标识为可用。优点1.预定义常量变量多对内存的请求有数百次避免了PHP向系统频繁的内存申请操作减少了对OS的请求次数。2.运行速度会更快缺点是随着程序的运行时间的变长内存使用越来越多所以5.3引入新垃圾回收机制。详细分析如下

PHP的内存管理可以被看作是分层hierarchical的。 它分为三层存储层storage、堆层heap和接口层emalloc/efree。 存储层通过 malloc()、mmap() 等函数向系统真正的申请内存并通过 free() 函数释放所申请的内存。 存储层通常申请的内存块都比较大这里申请的内存大并不是指storage层结构所需要的内存大 只是堆层通过调用存储层的分配方法时其以大块大块的方式申请的内存存储层的作用是将内存分配的方式对堆层透明化。如图下所示PHP内存管理器。PHP在存储层共有4种内存分配方案: mallocwin32mmap_anonmmap_zero 默认使用malloc分配内存如果设置了ZEND_WIN32宏则为windows版本调用HeapAlloc分配内存 剩下两种内存方案为匿名内存映射并且PHP的内存方案可以通过设置环境变量来修改。图6.1 PHP内存管理器一.内存的申请heap层是PHP内存管理的核心实现PHP底层对内存的管理 围绕着小块内存列表free_buckets、 大块内存列表large_free_buckets和 剩余内存列表rest_buckets三个列表来分层进行的。ZendMM向系统进行的内存申请并不是有需要时向系统即时申请 而是由ZendMM的最底层heap层先向系统申请一大块的内存通过对上面三种列表的填充 建立一个类似于内存池的管理机制。在程序运行需要使用内存的时候ZendMM会在内存池中分配相应的内存供使用。这样做的好处是避免了PHP向系统频繁的内存申请操作如下面的代码[php] view plain copy
  •   $tipi  "o_o\n";  
  •   echo $tipi;  
  • ?>  
  • 这是一个简单的php程序但通过对emalloc的调用计数只是PHP程序只赋值了一个变量而已但是却发现对内存的请求有数百次之多 当然这非常容易解释因为PHP脚本的执行需要大量的环境变量以及内部变量的定义(详细见PHP内核--生命周期) 这些定义本身都是需要在内存中进行存储的。在编写PHP的扩展时推荐使用emalloc(申请的是zend_mm_storage层的内存块)来代替malloc(申请的是操作系统的内存块)其实也就是使用PHP的ZendMM来代替 手动直接调用系统级的内存管理。ZendMM使用_zend_mm_alloc_int函数进行内存分配流程如下:从上面的分配可以看出PHP对内存的分配是结合PHP的用途来设计的PHP一般用于web应用程序的数据支持 单个脚本的运行周期一般比较短最多达到秒级内存大块整块的申请自主进行小块的分配 没有进行比较复杂的不相临地址的空闲内存合并而是集中再次向系统请求。 这样做的好处就是运行速度会更快缺点是随着程序的运行时间的变长 内存的使用情况会“越来越多”PHP5.2及更早版本。 所以PHP5.3之前的版本并不适合做为守护进程长期运行。 当然可以有其他方法解决而且在PHP5.3中引入了新的GC机制详见后边小节PHP内核--内存泄漏与新垃圾回收机制二.内存的销毁ZendMM在内存销毁的处理上采用与内存申请相同的策略当程序unset一个变量或者是其他的释放行为时ZendMM并不会直接立刻将内存交回给系统而是只在自身维护的内存池(storge层)中将其重新标识为可用 按照内存的大小整理到上面所说的三种列表small,large,free之中以备下次内存申请时使用。内存销毁的最终实现函数是_efree。在_efree中内存的销毁首先要进行是否放回cache的判断。 如果内存的大小满足ZEND_MM_SMALL_SIZE并且cache还没有超过系统设置的ZEND_MM_CACHE_SIZE 那么当前内存块zend_mm_block就会被放回mm_heap->cache中。 在内存的销毁过程中还涉及到引用计数和垃圾回收GC将在后边小节进行讨论。参见PHP内核--内存泄漏与新垃圾回收机制三.缓存在维基百科中有这样一段描述 凡是位于速度相差较大的两种硬件之间的用于协调两者数据传输速度差异的结构均可称之为Cache。 从最初始的处理器与内存间的Cache开始都是为了让数据访问的速度适应CPU的处理速度 其基于的原理是内存中“程序执行与数据访问的局域性行为”。 同样PHP内存管理中的缓存也是基于“程序执行与数据访问的局域性行为”的原理。 引入缓存就是为了减少小块内存块的查询次数(查询前先看是否能命中缓存)为最近访问的数据提供更快的访问方式。PHP将缓存添加到内存管理机制中做了如下一些操作·标识缓存和缓存的大小限制即何时使用缓存在某些情况下可以以最少的修改禁用掉缓存·缓存的存储结构即缓存的存放位置、结构和存放的逻辑·初始化缓存·获取缓存中内容·写入缓存释放缓存或者清空缓存列表缓存本身也是存储在storage层申请的内存中的如果内存都不够用了那就得释放缓存啦。当堆的内存溢出时程序会调用zend_mm_free_cache释放缓存中。整个释放的过程是一个遍历数组 对于每个数组的元素程序都遍历其所在链表中在自己之前的元素执行合并内存操作减少堆结构中缓存计量数字。
    网友评论