<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

              首先看了一下官方手冊,只有php5.3版本以后的才有了所謂的新的垃圾回收機制GC,那么以前是怎么干的呢?以前是基于引用計數的方式,這里就需要提一下引用計數的知識,官方手冊里面說php的每個變量都是存在一個叫做zval的容器里面,這個容器不僅包含了這個變量的值和類型,還包含了另外兩個重要的信息,“is_ref”和“refcount”,“is_ref”看名字就應該知道大概和引用相關,它是一個bool值,如果這個值是true那么代表這是一個引用變量,否則是普通變量。“refcount”指的是有多少個變量(符號)指向這個zval容器。

        比如一個變量$a="test",如果我們php安裝了xdebug插件并且開啟了插件,就可以用xdebug_debug_zval(“a”)來顯示zval里面的值。這里會輸出a:(refcount=1,is_ref=0)=“test”,可以看到refcount=1,因為這里有一個變量(符號)$a指向了這個zval容器,is_ref=0說明這個存放的是一個普通變量。

        如果我們進行一個操作$b=$a呢?按照常規的思路,應該是把$a的值復制一份給$b,然后$b也存放在另一個zval容器中,這個zval容器內容和$a那個一樣。真的是這樣嗎?我們用xdebug_debug_zval(“a”)先輸出$a對應的zval容器值,結果會輸出a:(refcount=2,is_ref=0)="test",這里refcount變成了2 ,說明除了$a還有一個變量(符號)指向這個zval容器,那就是$b了啊,這么一來$a和$b指向的是同一個zval容器,那不是修改$b也會影響到$a了?其實不會的,因為當$b或者$a的值改變的時候,這個zval容器的refcount會減一,然后會復制一份讓改變值的那個變量(符號)指向新的zval容器,這個時候就是我們剛才常規思路想的一樣了,有了兩個zval容器都是(refcount=1,is_ref=0)只是兩個容器的值和類型分別是$a和$b的值和類型。

        那如果是引用賦值$c=&$a呢?這時$a和$c同樣也指向同一個zval,即a,c:(refcount=2,is_ref=1)="test",這時候不光refcount加一,is_ref也變成了1也就是true,說明這是引用變量,那么改變$a和$c任何一個都會影響另一個的值。我們如果使用unset($c)的話,$a指向的容器的refcount就會減一變成1。如果我們再unset($a)的話,指向的zval容器的refcount就是0了,這個時候說明已經沒有變量(符號)指向這個容器了,那么php引擎就會從內存中銷毀釋放這個容器。

        那如果$a是一個數組呢,它指向的zval容器會是怎樣的?比如$a=array("1","2"),xdebug_debug_zval(“a”)會輸出如下的信息:

      a: (refcount=1, is_ref=0)=array (
         0 => (refcount=1, is_ref=0)='1',
         1 => (refcount=1, is_ref=0)='2'
      )

        可以看到除了$a本身指向一個zval容器存放外,它的每一個元素也都分別指向一個zval容器,如果我要這樣往$a中添加元素會怎樣?

      $a = array( 'meaning' => 'life', 'number' => 42 );
      $a['life'] = $a['meaning'];   //這里直接拿官方示例

        這個時候xdebug_debug_zval(“a”)會輸出: key為'meaning'和'life'的值指向同一個zval容器,refcount=2

      a: (refcount=1, is_ref=0)=array (
         'meaning' => (refcount=2, is_ref=0)='life',
         'number' => (refcount=1, is_ref=0)=42,
         'life' => (refcount=2, is_ref=0)='life'
      )

        如果我們在添加元素的時候,添加的是對數組本身的引用,又會變成什么樣?

      <?php
      $a = array( 'one' );
      $a[] =& $a;
      xdebug_debug_zval( 'a' );
      ?>

      這時會輸出:

      a: (refcount=2, is_ref=1)=array (
         0 => (refcount=1, is_ref=0)='one',
         1 => (refcount=2, is_ref=1)=...
      )

        $a數組本身指向的容器refcount變成了2,因為$a和$a[1]指向了這個容器,然而$a[1]又是$a的元素,這個元素又引用了$a本身,這就形成了一個閉環。

        如果這個時候來一句unset($a)呢?$a指向的容器refcount減一就會變成1,這個時候對于我們程序員來說已經不存在有可操作的變量(符號)指向這個容器了,但是refcount=1那么php引擎就不會銷毀這個容器。

        那不是這個容器在內存中不就成了垃圾了嗎?這種情況如果沒有垃圾回收機制GC,那么就只有等到當前請求結束,腳本結束自動清除了。但是有時候我們會用到一些遞歸或者死循環這類的來做一些特殊的業務邏輯,這時候內存如果有上面的情況出現,就會導致內存泄漏,消耗很大的內存空間。

        所以才有了5.3版本新的內存回收機制的出現。先說說機制的三個基本規則:

      • 如果一個zval容器的refcount增加,說明有新的變量(符號)指向這個容器,那么這個容器當然不會是垃圾,它將被繼續使用。
      • 如果一個zval容器的refcount減少到0了,那么說明沒有變量(符號)指向這個容器,它就會被php引擎銷毀。
      • 如果一個zval容易的refcount減少了,但是不是0,那么這個容器就有可能是垃圾,就會被垃圾回收機制所管理。

        怎么管理這些容器并判斷哪些是垃圾呢?當發現某個容器有可能是垃圾時,這個容器會被放進一個內存緩沖區,當緩沖區滿了時,就會進行垃圾回收算法來找出垃圾并銷毀。這里具體的算法可以看看官方文檔,我就用一個網友的總結來描述:

        對于一個包含環形引用的數組,對數組中包含的每個元素的zval進行減1操作,之后如果發現數組自身的zval的refcount變成了0,那么可以判斷這個數組是一個垃圾。

        這個道理其實很簡單,假設數組a的refcount等于m, a中有n個元素又指向a,如果m等于n,那么算法的結果是m減n,m-n=0,那么a就是垃圾,如果m>n,那么算法的結果m-n>0,所以a就不是垃圾了。m=n代表什么?  代表a的refcount都來自數組a元素的指向,代表除了a中的元素沒有任何變量(符號)指向根zval容器,代表用戶代碼空間中無法再訪問到這個zval,代表a是泄漏的內存,因此GC將a這個垃圾回收了。

        最后在哪里可以設置這個回收機制呢?默認的,PHP的垃圾回收機制是打開的,然后在配置文件 php.ini 里允許你修改它:zend.enable_gc 。除了修改配置zend.enable_gc是否開啟 ,也能通過分別調用gc_enable() 和 gc_disable()函數來打開和關閉垃圾回收機制。調用這些函數,與修改配置項來打開或關閉垃圾回收機制的效果是一樣的。如果想在根緩沖區還沒滿時強制執行周期回收,可以調用gc_collect_cycles()函數,這個函數將返回使用這個算法回收的周期數。

        當垃圾回收機制打開時,每當根緩存區存滿時,就會執行查找算法。根緩存區有固定的大小,可存10,000個可能根,當然可以通過修改PHP源碼文件Zend/zend_gc.c中的常量GC_ROOT_BUFFER_MAX_ENTRIES,然后重新編譯PHP,來修改這個10,000值。當垃圾回收機制關閉時,循環查找算法永不執行,然而,可能根將一直存在根緩沖區中,不管在配置中垃圾回收機制是否激活。

        當垃圾回收機制關閉時,如果根緩沖區存滿了可能根,更多的可能根顯然不會被記錄。那些沒被記錄的可能根,將不會被這個算法來分析處理。如果他們是循環引用周期的一部分,將永不能被清除進而導致內存泄漏。

        即使在垃圾回收機制不可用時,可能根也被記錄的原因是,相對于每次找到可能根后檢查垃圾回收機制是否打開而言,記錄可能根的操作更快。不過垃圾回收和分析機制本身要耗不少時間。

        也就是說關閉了回收機制也會往緩沖區丟疑似垃圾的容器,當緩沖區滿了的時候不會執行回收算法,后面更多的疑似垃圾容器不會繼續放進去,就可能導致內存泄漏。當開啟回收機制后,就會從緩沖區中之前放入的容器中開始垃圾回收機制。

      posted on 2020-05-06 17:15  周大媽  閱讀(255)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品午夜福利在线观看| 中文字幕无码中文字幕有码a| 无码人妻一区二区三区av| 亚洲精品国产精品不乱码| 成人av午夜在线观看| 曲阜市| 国产亚洲真人做受在线观看| 亚洲av成人无码精品电影在线| 美女把尿囗扒开让男人添| 综合色一色综合久久网| 国产成人免费观看在线视频| 免费看黄片一区二区三区| 豆国产97在线 | 亚洲| 国产极品视频一区二区三区 | 国产亚洲精品久久777777| 18禁一区二区每日更新| 黑人av无码一区| 亚洲中国精品精华液| 国产第一页浮力影院入口| 中年国产丰满熟女乱子正在播放| 亚洲精品国产无套在线观| 精品国偷自产在线视频99| 国产精品免费中文字幕| 久久精品av国产一区二区| 国产精品大全中文字幕| 无码中文字幕人妻在线一区| 天天躁夜夜躁av天天爽| 波多结野衣一区二区三区| 小嫩模无套内谢第一次| 亚洲精品tv久久久久久久久久| 无码人妻出轨黑人中文字幕| 少妇高潮喷水正在播放| 霍林郭勒市| 自拍亚洲综合在线精品| 亚洲高清免费在线观看| 中文字幕一区有码视三区| 午夜高清福利在线观看| 亚洲成人av在线高清| 国产成人高清亚洲综合| 欧美性猛交xxxx乱大交极品| 国产小视频一区二区三区|