搜尋
首頁後端開發PHP7PHP7垃圾回收機制詳解(附GC處理完整流程圖)

垃圾回收:

# 簡稱GC。顧名思義,就是廢物再利用的意思。
在說垃圾回收機制之前,先接觸一下記憶體洩漏。

推薦教學:《PHP7

記憶體洩漏:

某大神重口味充滿畫面感的形象解釋:

大概意思是申請了一塊地兒拉了會兒屎,拉完後不收拾,那麼那塊兒地就算是糟蹋了,地越用越少,最後一地全是屎。說到底一句,用了記得還。一定程度上說,垃圾回收機制就是用來擦屁股的。

c語言垃圾回收機制:

如果用過C語言,那麼申請記憶體的方式是malloc或是calloc,然後你用完這個記憶體後,一定不要忘了用free函數去釋放掉,這就是手動垃圾回收,通常都是大神用這種方式。

php的自動垃圾回收機制是怎麼樣的呢?

這個問題我們先這麼想,我們都知道php是C語言實現的。你想想如何用C語言實現對一個變數的統計以及釋放。 C語言是如何實現一個變量,從聲明開始到最後沒人用了,就把這個變量所佔的內存給釋放掉(被垃圾回收)。

PHP進行記憶體管理的核心演算法一共兩項:
一是引用計數,二是寫時拷貝

聲明一個PHP變數的時候,C語言在底層產生一個叫做zval的struct(結構體),如下:

zval {
string "a" //变量的名字是a
value zend_value //变量的值,联合体
type string //变量是字符串类型
}

zval struct結構體

(1)保存php $a的變數名稱
(2) php $a的變數類型
(3)php變數$a的zend_value聯合體

如果給變數賦值了,例如“hello world”,那麼C語言就在底層再產生一個叫做zend_value的union(聯合體)

zend_value {
string "hello world" //值的内容
refcount 1 //引用计数
}

zend_value的union(聯合體)

(1)保存php $a的變數的值hello world
(2)記錄php $a變數引用次數

看到zval struct結構體和zend_value,如果面試官問你php變數為什麼能夠保存字串"123"也能保存數字123,你知道該怎麼回答了吧?就答出重點zval中有該變數的型,當是字串123的時候,type就是string,此時value指向「123」;當是整數123的時候,zval的type為int,value為123。

何為引用計數?

程式碼實戰解析php變數參考計數

$a = 'hello,world';
echo xdebug_debug_zval( 'a');//refcount=1
$b = $a;
echo xdebug_debug_zval( 'a'); //$b引用$a,故变量a,refcount=2
$c = $a;
echo xdebug_debug_zval( 'a'); //$c引用$a,故变量a,refcount=3
unset( $c );
echo xdebug_debug_zval( 'a');//删除了$c的引用,故变量a,refcount=2

運行結果:

a:
(refcount=1, is_ref=0)string 'hello, world' (length=11)
a:
(refcount=2, is_ref=0)string 'hello,world' (length=11)
a:
(refcount=3, is_ref= 0)string 'hello,world' (length=11)
a:
(refcount=2, is_ref=0)string 'hello,world' (length=11)

#何為拷貝複製?

$a = 'hello';
$b = $a;//$a赋值给$b的时候,$a的值并没有真的复制了一份
echo xdebug_debug_zval( 'a');//$a的引用计数为2
$a = 'world';//当我们修改$a的值为123的时候,这个时候就不得已进行复制,避免$b的值和$a的一样
echo xdebug_debug_zval( 'a');///$a的引用计数为1

執行結果:

a:
(refcount=2, is_ref=0)string 'hello' (length=5)
a:
(refcount=1, is_ref=0)string 'world' (length=5)

其實,當你把$a賦值給$b的時候,$a的值並沒有真的複製了一份,這樣是對內存的極度不尊重,也是對時間複雜度的極度不尊重,計算機僅僅是將$b指向了$a的值而已,這就叫多快好省。那麼,什麼時候真正的發生複製呢?就是當我們修改$a的值為123的時候,這個時候就不得已進行複製,避免$b的值和$a的一樣。

透過簡單的案例解釋清楚了兩個要點:引用計數和寫入時拷貝。

垃圾回收機制:

當一個zval在被unset的時候、或是從一個函數中運行完畢出來(就是局部變數)的時候等等很多地方,都會產生zval與zend_value發生斷開的行為,這時候zend引擎需要偵測的就是zend_value的refcount是否為0,如果為0,則直接KO free空出內容來。如果zend_value的recount不為0,這個value不能被釋放,但是也不代表這個zend_value是清白的,因為此zend_value依然可能是個垃圾。

(1)當php變數$a的refcount=0時,變數$a就會被垃圾回收
(2)當php變數$a的refcount>0時,變數$ a但也可能被認為是垃圾

什麼樣的情況會導致zend_value的refcount不為0,但是這個zend_value卻是個垃圾呢?

$arr = [ 1 ];
$arr[] = &$arr;
unset( $arr );

这种情况下,zend_value不会能释放,但也不能放过它,不然一定会产生内存泄漏,所以这会儿zend_value会被扔到一个叫做垃圾回收堆中,然后zend引擎会依次对垃圾回收堆中的这些zend_value进行二次检测,检测是不是由于上述两种情况造成的refcount为1但是自身却确实没有人再用了,如果一旦确定是上述两种情况造成的,那么就会将zend_value彻底抹掉释放内存。

垃圾回收发生在什么时候?

有些同学可能有疑问,就是php不是运行一次就销毁了吗,我要gc有何用?并不是的,首先当一次fpm运行完毕后,最后一定还有gc的,这个销毁就是gc;其次是,内存都是即用即释放的,而不是攒着非得到最后,你想想一个典型的场景,你的控制器里的某个方法里用了一个函数,函数需要一个巨大的数组参数,然后函数还需要修改这个巨大的数组参数,你们应该是函数的运行范围里面修改这个数组,所以此时会发生写时拷贝了,当函数运行完毕后,就得赶紧释放掉这块儿内存以供给其他进程使用,而不是非得等到本地fpm request彻底完成后才销毁。

(1)fpm运行完毕后,最后一定会gc的
(2)运行过程中,也会gc的,内存都是即用即释放的,而不是攒着非得到最后gc

GC处理完整流程图

 

以上是PHP7垃圾回收機制詳解(附GC處理完整流程圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:csdn。如有侵權,請聯絡admin@php.cn刪除

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。