亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP的垃圾回收機制相關知識點整理

發布時間:2021-09-03 19:29:24 來源:億速云 閱讀:134 作者:chen 欄目:編程語言

本篇內容主要講解“PHP的垃圾回收機制相關知識點整理”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“PHP的垃圾回收機制相關知識點整理”吧!

PHP目前的開發框架,除了主流常用的FPM框架,想必就是基于swoole拓展的常駐內存開發了。

我們在FPM的開發模式中,每一次腳本程序結束之后,所有變量都會被銷毀,內存會被釋放,所以我們不用太擔心。

但是常駐內存開發模式就不一樣了,如果不注意變量內存的使用,無法很好的管理內存問題,會造成內存泄露。

所以,我們一定要熟悉PHP的垃圾回收機制(Garbage Collector 簡稱GC) 

寫時復制與引用計數

寫時復制

在PHP7+版本中,有關于變量內存的操作特性,采用了寫時復制,也就是說, 在必要的時候才會進行深拷貝(即發生寫的時候才會進行深拷貝).

當變量值為interned string字符串型(變量名,函數名,靜態字符串,類名等)時,變量值存儲在靜態區,內存回收被系統全局接管,引用計數將一直為1 。

當賦值變量的值為 整型,浮點型 時,php7底層將會直接把值存儲(php7的結構體將會直接存儲簡單數據類型),refcount將為0,我們用代碼來看一下:

$a = 'chris'.time();$b = $a;  //此時$b指向$a的同一個內存地址$c = $a;  //一樣xdebug_debug_zval('a');//a:(refcount=3, is_ref=0)string 'chris1614780053' (length=15)我們通過Xdebug來觀察變量的信息,他們指的都是同一個內存地址,是引用。
$a = 'chris'.time();$b = '青玄';$c = $a;xdebug_debug_zval('a');xdebug_debug_zval('b');//a:(refcount=2, is_ref=0)string 'chris1614780283' (length=15)
 //b:(interned, is_ref=0)string '青玄' (length=6) //存在了靜態區我們通過Xdebug來觀察變量的信息,這時$b的值已經發生了變化,這時候,才會使用新的內存空間,$a的引用次數-1。

引用計數

每個php變量存在一個叫”zval”的變量容器中。一個zval變量容器,除了包含變量的類型和值,還包括兩個字節的額外信息。第一個是”is_ref”,是個bool值,用來標識這個變量是否是屬于引用集合(reference set)。通過這個字節,php引擎才能把普通變量和引用變量區分開來,由于php允許用戶通過使用&來使用自定義引用,zval變量容器中還有一個內部引用計數機制,來優化內存使用。第二個額外字節是”refcount”,用以表示指向這個zval變量容器的變量(也稱符號即symbol)個數。

官方文檔的描述

簡單來說,就是給變量引用的次數進行計算,當計數refcount不等于0時,說明這個變量已經被引用,不能直接被回收,否則可以直接回收,用代碼來看看把

$a='chris'.time();$b=$a;$c=$a; $b='青玄';unset($c);xdebug_debug_zval('a');//a:(refcount=1, is_ref=0)string 'chris1614780526'(length=5)//我們可以看到,刪除$c,并不能把$a刪除,因為refcount=1

內存泄漏

function a(){class A {
   public $ref;
   public $name;

   public function __construct($name) { $this->name = $name; echo($this->name.'->__construct();'.PHP_EOL);
   }

   public function __destruct() {  echo($this->name.'->__destruct();'.PHP_EOL);
   }}$a1 = new A('$a1');$a2 = new A('$a2');$a3 = new A('$3');$a1->ref = $a2;$a2->ref = $a1;unset($a1);unset($a2);echo('exit(1);'.PHP_EOL);}a();echo('exit(2);'.PHP_EOL);

當$a1和$a2的屬性互相引用時,unset($a1,$a2) 只能刪除變量的引用,卻沒有真正的刪除類的變量,這是為什么呢?

首先,類的實例化變量分為2個步驟

1:開辟類存儲空間,用于存儲類數據

2:實例化一個變量,類型為class,值指向類存儲空間

當給變量賦值成功后,類的引用計數為1,同時,a1->ref指向了a2,導致a2類引用計數增加1,同時a1類被a2->ref引用,a1引用計數增加1

當unset時,只會刪除類的變量引用,也就是-1,但是該類其實還存在了一次引用(類的互相引用),

這將造成這2個類內存永遠無法釋放,直到被gc機制循環查找回收,或腳本終止回收(域結束無法回收).

PHP作用域的生命周期和變量回收

每個方法/函數都作為一個作用域,當運行完該作用域時,將會回收作用域內的所有變量,全局變量只有在腳本結束后才會回收。

我們可以通過以下方式來手動回收:

  • unset() : unset的回收原理其實就是引用計數-1,當引用計數-1之后為0時,將會直接回收該變量,否則不做操作(這就是上面內存泄漏的原因,引用計數-1并沒有等于0)。

  • 賦值為null :=null和unset($a),作用其實都為一致,null將變量值賦值為null,原先的變量值引用計數-1,而unset是將變量名從php底層變量表中清理,并將變量值引用計數-1,唯一的區別在于,=null,變量名還存在,而unset之后,該變量就沒了。

  • 變量覆蓋回收:通過給變量賦值其他值(例如null)進行回收,但是從程序的內存占用來說,覆蓋變量并不是意義上的內存回收,只是將變量的內存修改為了其他值.內存不會直接清空。

  • gc_collect_cycles :強制執行周期回收,在PHP執行中,一旦根緩沖區滿了或者調用gc_collect_cycles() 函數時,就會執行垃圾回收

另外:為避免不得不檢查所有引用計數可能減少的垃圾周期,PHP會有算法把疑似垃圾的變量,放在根緩沖區(root buffer)中,在根緩沖區滿了的時候,也會對垃圾緩沖區進行一次回收。

到此,相信大家對“PHP的垃圾回收機制相關知識點整理”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI

聂荣县| 庆阳市| 吉木乃县| 塘沽区| 库尔勒市| 广州市| 张家川| 江口县| 丽水市| 琼海市| 永昌县| 平邑县| 醴陵市| 江陵县| 衡南县| 巨野县| 鄄城县| 锡林浩特市| 鹤壁市| 桐乡市| 叶城县| 松潘县| 武城县| 平乡县| 理塘县| 江源县| 白朗县| 泰来县| 芦山县| 房山区| 嘉禾县| 西盟| 绵阳市| 兰西县| 灌阳县| 齐齐哈尔市| 故城县| 于都县| 扶绥县| 廉江市| 四川省|