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

转载 2018年04月16日 18:41:26
前言:

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种内存分配方案: malloc,win32,mmap_anon,mmap_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向系统频繁的内存申请操作,如下面的代码:
  1. <?php  
  2.   $tipi = "o_o\n";  
  3.   echo $tipi;  
  4. ?>  
这是一个简单的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释放缓存中。整个释放的过程是一个遍历数组, 对于每个数组的元素程序都遍历其所在链表中在自己之前的元素,执行合并内存操作,减少堆结构中缓存计量数字

PHP缓存机制

使用php自身的缓存机制如果要测试php自己的缓存机制, 需要配置php.ini 文件display_errors=On output_buffering=Off error_reporting= 设...
  • u014680098
  • u014680098
  • 2016-10-18 18:41:35
  • 107

UGUI内核大探究(零)

UGUI是Unity3D官方推出的UI系统,为了更好的使用UGUI,我们就需要去了解它。 UGUI代码开源,我们可以从bitbucket下载到源码。...
  • ecidevilin
  • ecidevilin
  • 2016-10-10 22:31:33
  • 4103

内存管理(Linux内核源码分析)

背景本篇博客试图通过linux内核源码分析linux的内存管理机制,并且对比内核提供的几个分配内存的接口函数。然后聊下slab层的用法以及接口函数。内核分配内存与用户态分配内存内核分配内存与用户态分配...
  • hty46565
  • hty46565
  • 2017-07-12 10:03:53
  • 1030

深入浅出Linux内核内存管理基础

1 背景知识 1.1 用户空间与内核空间内存的划分        从Linux操作系统层次上,内存可划分为用户空间内存和内核空间内存。        32位的CPU,最大寻址范围为2^32 - 1也就...
  • acs713
  • acs713
  • 2015-01-18 16:45:49
  • 4529

linux内核空间内存管理基本架构

内存管理,不用多说,言简意赅。在内核里分配内存还真不是件容易的事情,根本上是因为内核不能想用户空间那样奢侈的使用内存。       先来说说内存管理。内核把物理页作为内存管理的基本单位。尽管处理...
  • shenhuxi_yu
  • shenhuxi_yu
  • 2017-04-27 00:26:27
  • 314

内存管理-之内核内存管理-基于linux3.10

关于启动过程内存管理见《内存管理-之启动》 如果需要,内存管理三篇文章整理成pdf了,下载地址http://download.csdn.net/detail/shichaog/8662135 第四章...
  • shichaog
  • shichaog
  • 2015-05-05 22:22:04
  • 2014

php垃圾回收和内存管理机制

一、PHP 垃圾回收机制(Garbage Collector 简称GC) 在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾。PHP会将其在内存中销毁;这是PHP的GC垃圾处理机制,防止内存...
  • Wss0130
  • Wss0130
  • 2016-04-01 11:07:39
  • 3407

深入理解linux内核架构(内存管理)

1:在内核使用高端内存页之前,必须使用下文讨论的kmap和kunmap函数将其映射到内存虚拟地址空间中。 2:UMA计算机(一致内存访问,uniform memory access)将可用内存以连续方...
  • xueli1991
  • xueli1991
  • 2017-02-20 15:43:52
  • 1845

【Android Studio】深入探究webView的缓存机制

最近一直都在搞webview,搞过Android的人可能会知道,webView本身自带了缓存机制,company的需求是不用webView 的缓存机制,写自己的缓存机制,哇哈哈,有挑战性咯。写这篇博客...
  • u013598660
  • u013598660
  • 2015-07-25 09:59:17
  • 2142

Linux内核学习5:内存管理(1)

关于Linux内存管理的问题之前,先用一张图来
  • gzbaishabi
  • gzbaishabi
  • 2014-09-18 09:25:48
  • 668
收藏助手
不良信息举报
您举报文章:PHP内核--探究内存管理与缓存机制
举报原因:
原因补充:

(最多只允许输入30个字)