この記事では、PHP ガベージ コレクション メカニズムに関する高度なインタビューの質問を共有し、PHP ガベージ コレクション メカニズムを深く理解できるようにします。一定の参考値があるので、困っている友達が参考になれば幸いです。
#ps: この記事には、厳選されたインタビューの質問とナレッジ記事が含まれています。
PHP インタビューの質問 PHP のガベージ コレクション メカニズム、PHP のガベージ コレクション メカニズムの参照カウント (参照カウント) GC メカニズム、PHP は自動的にメモリを管理し、不要なオブジェクトを消去できます、PHP インタビューの質問で共有される PHP インタビューの質問ガベージ コレクション メカニズム:
推奨される学習: 「PHP ビデオ チュートリアル 」
PHP のガベージ コレクション メカニズムの紹介
PHP は参照カウント (参照カウント) GC メカニズムを使用し、ルート バッファ メカニズム。PHP は、循環参照を持つ zval があることを検出すると、それをルート バッファに配置します。ルート バッファが設定ファイルで指定された数に達すると、メモリ リークの問題を解決するためにガベージ リサイクルが行われます。循環参照によって。
各オブジェクトには参照カウンタ refcount が含まれています。各参照はオブジェクトに接続され、カウンタは 1 ずつ増加します。参照がリビング スペースから出るか、NULL に設定されると、カウンターは 1 ずつ減らされます。オブジェクトの参照カウンタがゼロになると、PHP はそのオブジェクトを使用する必要がなくなったことを認識し、そのオブジェクトが占有しているメモリ領域を解放します。
PHP ガベージ コレクションに関する次の記述のうち、間違っているものはどれですか?
A. ガベージ コレクション メカニズムのオン/オフは、php 設定を変更することで実現できます。
B. gc_enable() を使用してオン/オフにできます。プログラム内の gc_disable() と。
C. PHP のガベージ コレクション メカニズムにより、システムのパフォーマンスが大幅に向上します。
D. ガベージ コレクション メカニズムをオンにすると、メモリ リークが発生した場合に大量のメモリ領域を節約できますが、ガベージ コレクション アルゴリズムの実行には時間がかかるため、ガベージ コレクション アルゴリズムをオンにすると、スクリプトの実行時間が長くなります。
参考回答: C
回答分析: PHP のガベージ コレクション メカニズムは、リサイクル アルゴリズムが実際に実行されているときに消費時間を増やすだけです。ただし、通常の (小規模な) スクリプトでは、パフォーマンスへの影響はまったくありません。
#php ガベージ コレクション メカニズムに関する記述のうち、間違っているものはどれですか?
#A. ガベージ サイクルでは、参照カウントが 1 減っているかどうかをチェックし、どの変数コンテナの参照がゼロであるかをチェックして、どの部分がガベージであるかを見つけます。 B. gc_enable() および gc_disable() 関数を呼び出すことで、ガベージ コレクション メカニズムをオンまたはオフにできます C. 未使用の変数をクリーンアップしてメモリ使用量を節約します D、php ガベージ コレクションコードの実行後に自動的に実行されるため、ガベージ コレクションを手動で実行する必要はありません。参考回答: D回答分析: PHP コードの一部は、の実行には長い時間がかかりますが、この間に参照されていない変数があるとメモリ空間を占有し、動作が遅くなるなどの問題が発生します。
1. コンセプト
ガベージ コレクションは、次の機能です。ほとんどのプログラミング言語に含まれているメモリ管理メカニズム。ユーザーが手動でメモリを収集する必要があるアンマネージ言語: C、C、および Objective C とは対照的に、GC メカニズムを備えた言語: Java、JavaScript、および PHP はメモリを自動的に管理できます。ガベージ コレクション メカニズム (gc) は、その名前が示すように、廃棄物の再利用を意味し、動的なストレージ割り当てスキームです。プログラムで不要になった割り当てられたメモリ ブロックを自動的に解放します。ガベージ コレクション メカニズムにより、プログラマはプログラム メモリの割り当てについてあまり心配する必要がなく、ビジネス ロジックにより多くのエネルギーを注ぐことができます。 現在人気のあるさまざまな言語の中でも、ガベージ コレクション メカニズムは新世代の言語に共通の機能であり、Python、PHP、C#、Ruby などはすべてガベージ コレクション メカニズムを使用しています。
2. PHP ガベージ コレクション メカニズム
1. PHP5.3 バージョンより前では、使用されていたガベージ コレクション メカニズムは単純な「参照カウント」でした。 」。什麼叫做引用計數?
由於PHP是用C來寫的,C裡面有一個東西叫做結構體,我們PHP的變數在C中就是用這種方式儲存的。
每個PHP的變數都存在於一個叫做zval的容器中,一個zval容器,除了包含變數名稱和值,還包括兩個位元組的額外資訊:
● 一個叫做'is_ref',是個布林值,用來表示這個變數是否屬於引用集合,透過這個字節,我們php才能把普通變數和引用變數區分開來。
● 第二個額外位元組就是'refcount',用來表示指向這個容器的變數的個數。
即:
① 每個記憶體物件都分配一個計數器,當記憶體物件被變數引用時,計數器1;
② 當變數引用撤掉後(執行unset()後),計數器-1;
③ 當計數器=0時,表示記憶體物件沒有被使用,該記憶體物件則進行銷毀,垃圾回收完成。
並且PHP在一個生命週期結束後就會釋放此進程/執行緒所佔的內容,這種方式決定了PHP在前期不需要過多考慮記憶體的洩漏問題。
但是當兩個或多個物件互相引用形成環狀後,記憶體物件的計數器則不會消減為0;這時候,這一組記憶體物件已經沒用了,但是不能回收,從而導致記憶體外洩的現象。
php5.3開始,使用了新的垃圾回收機制,在引用計數基礎上,實作了一種複雜的演算法,來偵測記憶體物件中引用環的存在,以避免記憶體外洩。
如官方文件所說:每個php變數存在一個叫做"zval"的變數容器中。一個zval變數容器,除了包含變數的類型和值,還包括兩個位元組的額外資訊。第一個是"is_ref",是個bool值,用來識別這個變數是否是屬於引用集合(reference set)。透過這個位元組,php引擎才能把普通變數和引用變數區分開來,由於php允許使用者透過使用&來使用自訂引用,zval變數容器中還有一個內部引用計數機制,來優化記憶體使用。
第二個額外位元組是"refcount",用以表示指向這個zval變數容器的變數(也稱為符號即symbol)個數。所有的符號存在一個符號表中,其中每個符號都有作用域(scope)。
官方文件所說,可以使用Xdebug來檢查引用計數情況:
<?php $a = "new string"; $c = $b = $a; xdebug_debug_zval( 'a' ); unset( $b, $c ); xdebug_debug_zval( 'a' ); ?>
以上例程會輸出:
a: (refcount=3, is_ref=0)='new string' a: (refcount=1, is_ref=0)='new string'
注意:從PHP7的NTS版本開始,以上例程的參考將不再被計數,即#c=b=$a之後a的參考計數也是1.具體分類如下:
在PHP 7中,zval可以被引用計數或不被引用。在zval結構中有一個標誌確定了這一點。
① 對於null,bool,int和double的類型變量,refcount永遠不會計數;
② 對於物件、資源類型,refcount計數和php5的一致;
③ 對於字串,未被引用的變數稱為「實際字串」。而那些被引用的字串被重複刪除(即只有一個帶有特定內容的被插入的字串)並保證在請求的整個持續時間內存在,所以不需要為它們使用引用計數;如果使用了opcache,這些字串將存在於共享記憶體中,在這種情況下,您不能使用引用計數(因為我們的引用計數機制是非原子的);
④對於數組,未引用的變數稱為“不可變數組”。其陣列本身計數與php5一致,但陣列裡面的每個鍵值對的計數,則按前面三條的規則(即如果是字串也不在計數);如果使用opcache,則程式碼中的常數數組文字將會被轉換為不可變數組。
再次,這些生活在共享內存,因此不能使用refcounting。
我們的demo範例如下:
<?php echo '测试字符串引用计数'; $a = "new string"; $b = $a; xdebug_debug_zval( 'a' ); unset( $b); xdebug_debug_zval( 'a' ); $b = &$a; xdebug_debug_zval( 'a' ); echo '测试数组引用计数'; $c = array('a','b'); xdebug_debug_zval( 'c' ); $d = $c; xdebug_debug_zval( 'c' ); $c[2]='c'; xdebug_debug_zval( 'c' ); echo '测试int型计数'; $e = 1; xdebug_debug_zval( 'e' );
看到的輸出如下:
##三、回收週期
預設的,PHP的垃圾回收機制是打開的,然後有個php.ini設定允許你修改它:zend.enable_gc 。當垃圾回收機制開啟時,演算法會判斷每當根快取區存滿時,就會執行循環查找。根快取區有固定的大小,預設10,000,可以透過修改PHP原始碼檔案Zend/zend_gc.c中的常數GC_ROOT_BUFFER_MAX_ENTRIES,然後重新編譯PHP,來修改這個值。當垃圾回收機制關閉時,循環查找演算法永不執行,然而,根將一直存在根緩衝區中,不管在配置中垃圾回收機制是否啟動。
除了修改設定zend.enable_gc ,也能透過分別呼叫gc_enable() 和 gc_disable()函數在執行php時來開啟和關閉垃圾回收機制。呼叫這些函數,與修改配置項來開啟或關閉垃圾回收機制的效果是一樣的。即使在可能根緩衝區還沒滿時,也能強制執行週期回收。你能呼叫gc_collect_cycles()函數達到這個目的。這個函數將會傳回使用這個演算法回收的周期數。
允許打開和關閉垃圾回收機制並且允許自主的初始化的原因,是由於你的應用程式的某一部分可能是高時效性的。在這種情況下,你可能不想使用垃圾回收機制。當然,對你的應用程式的某部分關閉垃圾回收機制,是在冒著可能記憶體洩漏的風險,因為一些可能根也許存不進有限的根緩衝區。
因此,就在你呼叫gc_disable()函數釋放記憶體之前,先呼叫gc_collect_cycles()函數可能比較明智。因為這將清除已存放在根緩衝區中的所有可能根,然後在垃圾回收機制被關閉時,可留下空緩衝區以有更多空間存儲可能根。
四、效能影響
1、記憶體佔用空間的節省
#首先,實現垃圾回收機制的整個原因是為了一旦先決條件滿足,透過清理循環引用的變數來節省記憶體佔用。在PHP執行中,一旦根緩衝區滿了或呼叫gc_collect_cycles() 函數時,就會執行垃圾回收。
2、執行時間增加
垃圾回收影響效能的第二個領域是它釋放已洩漏的記憶體耗費的時間。
通常,PHP中的垃圾回收機制,僅在循環回收演算法確實運行時會有時間消耗上的增加。但是在平常的(更小的)腳本中應根本沒有效能影響。
3、在平常腳本中有循環回收機制運行的情況下,記憶體的節省將允許更多這種腳本同時運行在你的伺服器上。因為總共使用的記憶體沒達到上限。
這種好處在長時間運行腳本中尤其明顯,諸如長時間的測試套件或daemon腳本此類。同時,對通常比Web腳本運行時間長的腳本應用程序,新的垃圾回收機制,應該會大大改變一直以來認為內存洩漏問題難以解決的看法。
最後,祝所有大家在面試中過關斬將,拿到心儀offer。
更多程式相關知識,請造訪:程式設計入門! !
以上がPHP のガベージ コレクション メカニズムを理解するのに役立つ、インタビューでの質問を 3 つ厳選しました。 !の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。