PHP的垃圾回收機(jī)制相關(guān)知識(shí)點(diǎn)整理

本篇內(nèi)容主要講解“PHP的垃圾回收機(jī)制相關(guān)知識(shí)點(diǎn)整理”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“PHP的垃圾回收機(jī)制相關(guān)知識(shí)點(diǎn)整理”吧!

在臨朐等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需求定制設(shè)計(jì),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),營銷型網(wǎng)站建設(shè),成都外貿(mào)網(wǎng)站制作,臨朐網(wǎng)站建設(shè)費(fèi)用合理。

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

我們?cè)贔PM的開發(fā)模式中,每一次腳本程序結(jié)束之后,所有變量都會(huì)被銷毀,內(nèi)存會(huì)被釋放,所以我們不用太擔(dān)心。

但是常駐內(nèi)存開發(fā)模式就不一樣了,如果不注意變量?jī)?nèi)存的使用,無法很好的管理內(nèi)存問題,會(huì)造成內(nèi)存泄露。

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

寫時(shí)復(fù)制與引用計(jì)數(shù)

寫時(shí)復(fù)制

在PHP7+版本中,有關(guān)于變量?jī)?nèi)存的操作特性,采用了寫時(shí)復(fù)制,也就是說, 在必要的時(shí)候才會(huì)進(jìn)行深拷貝(即發(fā)生寫的時(shí)候才會(huì)進(jìn)行深拷貝).

當(dāng)變量值為interned string字符串型(變量名,函數(shù)名,靜態(tài)字符串,類名等)時(shí),變量值存儲(chǔ)在靜態(tài)區(qū),內(nèi)存回收被系統(tǒng)全局接管,引用計(jì)數(shù)將一直為1 。

當(dāng)賦值變量的值為 整型,浮點(diǎn)型 時(shí),php7底層將會(huì)直接把值存儲(chǔ)(php7的結(jié)構(gòu)體將會(huì)直接存儲(chǔ)簡(jiǎn)單數(shù)據(jù)類型),refcount將為0,我們用代碼來看一下:

$a = 'chris'.time();$b = $a;  //此時(shí)$b指向$a的同一個(gè)內(nèi)存地址$c = $a;  //一樣xdebug_debug_zval('a');//a:(refcount=3, is_ref=0)string 'chris1614780053' (length=15)我們通過Xdebug來觀察變量的信息,他們指的都是同一個(gè)內(nèi)存地址,是引用。
$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) //存在了靜態(tài)區(qū)我們通過Xdebug來觀察變量的信息,這時(shí)$b的值已經(jīng)發(fā)生了變化,這時(shí)候,才會(huì)使用新的內(nèi)存空間,$a的引用次數(shù)-1。

引用計(jì)數(shù)

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

官方文檔的描述

簡(jiǎn)單來說,就是給變量引用的次數(shù)進(jìn)行計(jì)算,當(dāng)計(jì)數(shù)refcount不等于0時(shí),說明這個(gè)變量已經(jīng)被引用,不能直接被回收,否則可以直接回收,用代碼來看看把

$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刪除,因?yàn)閞efcount=1

內(nèi)存泄漏

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);

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

首先,類的實(shí)例化變量分為2個(gè)步驟

1:開辟類存儲(chǔ)空間,用于存儲(chǔ)類數(shù)據(jù)

2:實(shí)例化一個(gè)變量,類型為class,值指向類存儲(chǔ)空間

當(dāng)給變量賦值成功后,類的引用計(jì)數(shù)為1,同時(shí),a1->ref指向了a2,導(dǎo)致a2類引用計(jì)數(shù)增加1,同時(shí)a1類被a2->ref引用,a1引用計(jì)數(shù)增加1

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

這將造成這2個(gè)類內(nèi)存永遠(yuǎn)無法釋放,直到被gc機(jī)制循環(huán)查找回收,或腳本終止回收(域結(jié)束無法回收).

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

每個(gè)方法/函數(shù)都作為一個(gè)作用域,當(dāng)運(yùn)行完該作用域時(shí),將會(huì)回收作用域內(nèi)的所有變量,全局變量只有在腳本結(jié)束后才會(huì)回收。

我們可以通過以下方式來手動(dòng)回收:

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

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

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

  • gc_collect_cycles :強(qiáng)制執(zhí)行周期回收,在PHP執(zhí)行中,一旦根緩沖區(qū)滿了或者調(diào)用gc_collect_cycles() 函數(shù)時(shí),就會(huì)執(zhí)行垃圾回收

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

到此,相信大家對(duì)“PHP的垃圾回收機(jī)制相關(guān)知識(shí)點(diǎn)整理”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

當(dāng)前名稱:PHP的垃圾回收機(jī)制相關(guān)知識(shí)點(diǎn)整理
網(wǎng)頁鏈接:http://bm7419.com/article10/jjcpdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站手機(jī)網(wǎng)站建設(shè)、ChatGPT、Google、網(wǎng)站內(nèi)鏈、App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)