最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 大话PHP中垃圾回收机制的解析

    正文概述 转载于:掘金(程序员安安)   2021-04-13   480

    前言

    平时经常听到很多人说到的gc,就是垃圾回收器,全称Garbage Collection

    早期版本,准确地说是5.3之前(不包括5.3)的垃圾回收机制,是没有专门的垃圾回收器的。只是简单的判断了一下变量的zval的refcount是否为0,是的话就释放否则不释放直至进程结束。

    乍一看确实没毛病啊,然而其中隐藏着变量内存溢出的风险:bugs.php.net/bug.php?id=… ,无法回收的内存造成了内存泄漏,所以PHP5.3出现了专门负责清理垃圾数据、防止内存泄漏的GC。

    php引用计数基本知识点

    不准确但却通俗的说: refcount:多少个变量是一样的用了相同的值,这个数值就是多少。 is_ref:bool类型,当refcount大于2的时候,其中一个变量用了地址&的形式进行赋值,好了,它就变成1了。

    主要讲讲如何用php来直观的看到这些计数的变化,走一波。 首先需要在php上装上xdebug的扩展。

    字符串类型变量

    1.查看内部结构

    <?php
        $name = "公众号:PHP开源社区";
        xdebug_debug_zval('name');
    

    会得到:

    name:(refcount=1, is_ref=0),string '公众号:PHP开源社区' (length=18)
    

    2.增加一个计数

    <?php
        $name = "公众号:PHP开源社区";
        $temp_name = $name;
        xdebug_debug_zval('name');
    

    会得到:

    name:(refcount=2, is_ref=0),string '公众号:PHP开源社区' (length=18)
    

    看到了吧,refcount+1了。

    3.引用赋值

    <?php
        $name = "公众号:PHP开源社区";
        $temp_name = &$name;
        xdebug_debug_zval('name');
    

      会得到:

    name:(refcount=2, is_ref=1),string '公众号:PHP开源社区' (length=18)
    

    是的引用赋值会导致zval通过is_ref来标记是否存在引用的情况。

    数组型的变量

    <?php
        $name = ['a'=>'公众号', 'b'=>'PHP开源社区'];
        xdebug_debug_zval('name');
    

    会得到:

    name:
    (refcount=1, is_ref=0),
    array (size=2)
      'a' => (refcount=1, is_ref=0),string '公众号' (length=9)
      'b' => (refcount=1, is_ref=0),string 'PHP开源社区' (length=9)
    

    还挺好理解的,对于数组来看是一个整体,对于内部kv来看又是分别独立的整体,各自都维护着一套zval的refount和is_ref。

    销毁变量

    <?php
        $name = "公众号:PHP开源社区";
        $temp_name = $name;
        xdebug_debug_zval('name');
        unset($temp_name);
        xdebug_debug_zval('name');
    

    会得到:

    name:(refcount=2, is_ref=0),string '公众号:PHP开源社区' (length=18)
    name:(refcount=1, is_ref=0),string '公众号:PHP开源社区' (length=18)
    

    refcount计数减1,说明unset并非一定会释放内存,当有两个变量指向的时候,并非会释放变量占用的内存,只是refcount减1.

    php的内存管理机制

    知道了zval是怎么一回事,接下来看看如何通过php直观看到内存管理的机制是怎么样的。

    外在的内存变化

    <?php
        //获取内存方法,加上true返回实际内存,不加则返回表现内存
        var_dump(memory_get_usage());
        $name = "公众号:PHP开源社区";
        var_dump(memory_get_usage());
        unset($name);
        var_dump(memory_get_usage());
    

    会得到:

    int 1593248
    int 1593384
    int 1593248
    

    大致过程:定义变量->内存增加->清除变量->内存恢复

    潜在的内存变化

    当执行 时候,内存的分配做了两件事情:

    1.为变量名分配内存,存入符号表

    2.为变量值分配内存

    $name = "公众号:PHP开源社区";
    

    再来看代码:

    <?php
    
        var_dump(memory_get_usage());
        for($i=0;$i<100;$i++)
        {
            $a = "test".$i;
            $$a = "hello";    
        }
        var_dump(memory_get_usage());
        for($i=0;$i<100;$i++)
        {
            $a = "test".$i;
             unset($$a);    
        }
        var_dump(memory_get_usage());
    

    会得到:

    int 1596864
    int 1612080
    int 1597680
    

    简直爆炸,怎么和之前看的不一样?内存没有全部回收回来。

    对于php的核心结构Hashtable来说,由于未知性,定义的时候不可能一次性分配足够多的内存块。所以初始化的时候只会分配一小块,等不够的时候在进行扩容,而Hashtable只扩容不减少,所以就出现了上述的情况:当存入100个变量的时候,符号表不够用了就进行一次扩容,当unset的时候只释放了”为变量值分配内存”,而“为变量名分配内存”是在符号表的,符号表并没有缩小,所以没收回来的内存是被符号表占去了。

    潜在的内存申请与释放设计

    php和c语言一样,也是需要进行申请内存的,只不过这些操作作者都封装到底层了,php使用者无感知而已。

    php并非简单的向os申请内存,而是会申请一大块内存,把其中一部分分给申请者,这样当再有逻辑来申请内存的时候,就不需要向os申请了,避免了频繁调用。当内存不够的时候才会再次申请

    当释放内存的时候,php并非会把内存还给os,而是把内存轨道自己维护的空闲内存列表,以便重复利用。

    以上内容希望帮助到大家,更多免费PHP大厂PDF,PHP进阶架构视频资料,PHP精彩好文可以微信搜索关注:PHP开源社区

    2021金三银四大厂面试真题集锦,必看!

    四年精华PHP技术文章整理合集——PHP框架篇

    四年精华PHP技术文合集——微服务架构篇

    四年精华PHP技术文合集——分布式架构篇

    四年精华PHP技术文合集——高并发场景篇

    四年精华PHP技术文章整理合集——数据库篇


    起源地下载网 » 大话PHP中垃圾回收机制的解析

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元