首頁 後端開發 php教程 php垃圾回收之回收计策和算法

php垃圾回收之回收计策和算法

Jun 13, 2016 pm 12:03 PM
root unset xdebug zval

php垃圾回收之回收策略和算法

一、垃圾回收实现方式

? ? ?在以前的php中用到的是引用计数机制处理垃圾回收问题,但是这个机制存在一个弊端,就是无法处理循环引用引起的内存泄露。然而在php5.3.0以后的版本中(包含5.3.0)使用了专门GC机制(同步算法)清理垃圾,来处理这个内存泄露问题。下面就是介绍它是如何实现的:

? ??首先要了解几个基本的准则:

1:如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾。

2:如果一个zval的refcount减少到0,?那么zval可以被释放掉,属于垃圾。

3:如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾。

? ? ?只有在准则3下,GC才会把zval收集起来,然后通过新的算法来判断此zval是否为垃圾。那么如何判断这么一个变量是否为真正的垃圾呢?简单的说,就是对此zval中的每个元素进行一次refcount减1操作,操作完成之后,如果zval的refcount=0,那么这个zval就是一个垃圾。这个原理咋看起来很简单,但是又不是那么容易理解,下面通过结构图来深入理解:


? ? ?A:为了避免每次变量的refcount减少的时候都调用GC的算法进行垃圾判断,此算法会先把所有前面准则3情况下的zval节点放入一个节点(root)缓冲区(root buffer),并且将这些zval节点标记成紫色,同时算法必须确保每一个zval节点在缓冲区中之出现一次。当缓冲区被节点塞满的时候,GC才开始开始对缓冲区中的zval节点进行垃圾判断。

? ? ?B:当缓冲区满了之后,算法以深度优先对每一个节点所包含的zval进行减1操作,为了确保不会对同一个zval的refcount重复执行减1操作,一旦zval的refcount减1之后会将zval标记成灰色。需要强调的是,这个步骤中,起初节点zval本身不做减1操作,但是如果节点zval中包含的zval又指向了节点zval(环形引用),那么这个时候需要对节点zval进行减1操作。

? ? ?C:算法再次以深度优先判断每一个节点包含的zval的值,如果zval的refcount等于0,那么将其标记成白色(代表垃圾),如果zval的refcount大于0,那么将对此zval以及其包含的zval进行refcount加1操作,这个是对非垃圾的还原操作,同时将这些zval的颜色变成黑色(zval的默认颜色属性)

? ? ?D:遍历zval节点,将C中标记成白色的节点zval释放掉。

二、举例详解垃圾回收过程

? ? ?通过上面的说明,大家可能已经有了一定的印象,那实际应用中是如何具体操作的呢?下面就通过例子说明:

? ? ①在刚刚声明变量并赋值的情况下,其实就相当于准则1(如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾),变量不是垃圾,也不会进行gc检查。

$a = "one";$b = array();$b[] = $a;$b[] = & $b;$c = "two";//声明了三个变量$a、$b、$c。这个时候refcount都是增加的情况,变量不是垃圾也不会放入到root缓冲器等待垃圾检查。xdebug_debug_zval( 'a' );  xdebug_debug_zval( 'b' );  xdebug_debug_zval( 'c' );  //输出分别如下:a: (refcount=2, is_ref=0)='one'b: (refcount=2, is_ref=1)=array (     0 => (refcount=2, is_ref=0)='one',     1 => (refcount=2, is_ref=1)=... )  c: (refcount=1, is_ref=0)='two'
登入後複製

? ?②在上面的基础上,我们调用了unset()函数释放变量b和c。如下:

unset($b);unset($c);xdebug_debug_zval( 'a' ); //输出如下:a: (refcount=2, is_ref=0)='one'
登入後複製

? ? ?调用unset函数后,$b和$c对应容器中的refcount都会减1,但是他们的效果却不相同:先看$c调用unset($c)后,$c的refcount就编程了0,符合准则2,则$c对应的zval容器就是垃圾会被回收;再看$b调用unset($b)后,但是$b的第1个引用仍然指向$b所对应的zval容器,只不过$b对应的zval容器的refcount会减1,值会从2变成1。这时候容器的refcount虽然减1,但仍然不为零,则符合准则3,会把$b对应的zval,放入到root缓冲区中。等待gc垃圾校验操作,也就是进入到了(二)中的(A)情况。

? ? ?③在往后的操作就是(二)中描述的了。经历(二)中的ABCD过程后,变量$b对应的zval容器会被释放,完成了垃圾回收,也解决了循环引用的内存泄露问题。

三、垃圾回收器配置使用

? ? ?在PHP中,GC默认是开启的,你可以通过ini文件中的?zend.enable_gc 项来开启或则关闭GC。当GC开启的时候,垃圾分析算法将在节点缓冲区(roots buffer)满了之后启动。缓冲区默认可以放10,000个值,当然你也可以通过修改Zend/zend_gc.c中的GC_ROOT_BUFFER_MAX_ENTRIES?来改变这个数值,需要重新编译链接PHP。当GC关闭的时候,垃圾分析算法就不会运行,但是相关节点还会被放入节点缓冲区,这个时候如果缓冲区节点已经放满,那么新的节点就不会被记录下来,这些没有被记录下来的节点就永远也不会被垃圾分析算法分析。如果这些节点中有循环引用,那么有可能产生内存泄漏。之所以在GC关闭的时候还要记录这些节点,是因为简单的记录这些节点比在每次产生节点的时候判断GC是否开启更快,另外GC是可以在脚本运行中开启的,所以记录下这些节点,在代码运行的某个时候如果又开启了GC,这些节点就能被分析算法分析。当然垃圾分析算法是一个比较耗时的操作。

??? 在PHP代码中我们可以通过gc_enable()和gc_disable()函数来开启和关闭GC,也可以通过调用gc_collect_cycles()在节点缓冲区未满的情况下强制执行垃圾分析算法。这样用户就可以在程序的某些部分关闭或则开启GC,也可强制进行垃圾分析算法。?

? ? ?

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡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脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

以超級使用者登入Ubuntu 以超級使用者登入Ubuntu Mar 20, 2024 am 10:55 AM

在Ubuntu系統中,root使用者通常是停用狀態的。要啟動root用戶,可以使用passwd指令設定密碼,然後使用su-指令以root身分登入。根用戶是具有系統管理權限且不受限制的使用者。他擁有存取和修改檔案、使用者管理、軟體安裝和刪除,以及系統配置變更等權限。根用戶與一般用戶有著明顯的區別,根用戶擁有系統中最高的權限和更廣泛的控制權。根用戶可以執行重要的系統命令和編輯系統文件,而普通用戶則無法做到這一點。在本指南中,我將探討Ubuntu根用戶,如何以根用戶身份登錄,以及它與一般用戶的不同之處。注意

Nginx設定中指令root和alias的差別是什麼 Nginx設定中指令root和alias的差別是什麼 May 12, 2023 pm 12:16 PM

root和alias都可以定義在location模組中,都是用來指定請求資源的真實路徑,例如:location/i/{root/data/w3;}請求http://foofish.net/i/top.gif這個位址時,那麼在伺服器裡面對應的真正的資源是/data/w3/i/top.gif檔案注意:真實的路徑是root指定的值加上location指定的值。而alias正如其名,alias指定的路徑是location的別名,不管location的值怎麼寫,資源的真實路徑都是alias指定的路徑,例如

手把手使用 Python 刪除 Windows 下的長路徑文件 手把手使用 Python 刪除 Windows 下的長路徑文件 Apr 12, 2023 pm 01:31 PM

0x01 文章背景近期,筆者所在公司的某業務系統的儲存臨近極限,伺服器馬上就要跑不動了,由於該業務系統A包含多個子系統A1、A2、A3 ... An,這些子系統的中間儲存檔案由於設計原因,都儲存在同一個父級目錄之內,唯一不同的是,不同子系統產生的檔案和資料夾的名字都以該子系統名稱開始。如A1子系統產生的檔案命名方式均為A1xxxxxx, A2子系統產生的檔案名稱均為A2xxxxx。現在要刪除其中一些子系統的歷史文件,以釋放伺服器空間,幾十T的數據,存放在一起,手動刪除肯定不顯示,只能藉助程式自動化

Linux怎麼修改root使用者名稱 Linux怎麼修改root使用者名稱 May 18, 2023 pm 07:50 PM

1.以CentOS為例,登入後修改/etc/passwd與/etc/shadow,第一行開始的root改為新的使用者名稱(例如admin),修改之後透過wq!儲存。 2、修改並儲存後,重新啟動伺服器後即可生效,可以看下檔案的權限,可以看到所屬帳號一欄變為admin了,如下:註:在Linux中預設的最高管理權限使用者是root,uid為0。在系統中只辨識uid,因此只要uid為0,系統就視為最高管理使用者。但對於應用程式可能會有一定的問題,有些軟體預設使用的是root用戶,所以在對軟體應用的了解有限的情況

手機root的好處與壞處 手機root的好處與壞處 Jul 06, 2023 pm 04:53 PM

手機root的好處:1、可以備份系統;2、可以使用進階的程式;3、可以修改、可以移除系統的程式;4、可以把程式安裝在sd卡上;5、可以修改系統字型等等。壞處:1、手機root後容易被木馬病毒侵入;2、可能因為不徹底以及軟體相容性等問題,導致系統損壞出現系統運作問題;3、手機root後軟體錯誤系統檔案導致系統錯誤;4、手機root後用戶隱私有外洩風險等等。

在生產伺服器上啟用XDebug會使PHP變慢嗎? 在生產伺服器上啟用XDebug會使PHP變慢嗎? Sep 22, 2023 pm 10:41 PM

是的,像XDebug這樣的偵錯器會降低PHP伺服器的效能。這就是調試器不放置在伺服器環境中的原因。它們部署在不同的環境中,以避免不必要的開銷。偵錯訊息無法在已處於生產階段的應用程式中顯示。當將偵錯行為加入伺服器上,偵錯引擎附加到PHP進程。它開始接收訊息以在斷點處停止,但這不是必需的行為,因為它會給其他進程帶來高效能打擊,從而停止PHP解析器。另一方面,當調試器安裝後,它們往往會在伺服器中打開端口,因為它們不打算在生產環境中使用。在伺服器中打開連接埠就像為駭客打開一扇窺探之門一樣糟糕。

PHP是如何儲存變數的? zval結構體你了解嗎? PHP是如何儲存變數的? zval結構體你了解嗎? May 26, 2022 am 09:47 AM

在 PHP 中定義一個變數是不需要宣告類型的,一開始給變數 $a 一個整數值,後面又可以輕易地將其改變為其他類型。那在 PHP 的源碼中是如何來儲存這個變數 $a 的呢?帶著這個疑問我們一起去看 PHP 的原始碼。

PHP8.0中的偵錯程式庫:Xdebug PHP8.0中的偵錯程式庫:Xdebug May 14, 2023 am 08:09 AM

在PHP開發中,調試是不可避免的部分。為了幫助開發者更容易除錯自己的程式碼,PHP8.0在其偵錯程式庫中引入了一個非常有用的工具:Xdebug。本文將介紹Xdebug的一些主要功能,以及如何使用它來簡化PHP調試的過程。 Xdebug是一款開源偵錯工具,可在PHP應用程式中捕獲錯誤,並提供詳細的錯誤堆疊追蹤信息,以及正在使用的變數。它可以幫助開發人員檢測和解決程式碼

See all articles