ホームページ >バックエンド開発 >PHPチュートリアル >PHPにおけるGCの仕組みを詳しく解説

PHPにおけるGCの仕組みを詳しく解説

*文
*文オリジナル
2017-12-27 14:12:384360ブラウズ

この記事では、PHP におけるガベージ コレクション機構の解釈を中心に紹介します。GC 機能の有無は、プログラミング言語の開発において重要な問題です。お役に立てれば幸いです。

PHP の基本的な GC 概念
PHP 言語には、他の言語と同様にガベージ コレクション メカニズムがあります。したがって、今日説明したいことは、PHP ガベージ コレクション メカニズムに関連するものです。お役に立てれば幸いです。 PHP strtotime アプリケーションのエクスペリエンス PHPmemory_get_usage() はメモリを管理します PHP unset グローバル変数の使用問題の詳細な説明 PHP unset() 関数は変数を破棄し、PHP の完全なサイト権限検証を迅速に実装する方法を説明します 1. PHP ガベージ コレクション メカニズム (ガベージ コレクター、参照) PHP では GC として)、このオブジェクトを指す変数がない場合、このオブジェクトはガベージになります。 PHP はこれをメモリ内で破棄します。これは、メモリのオーバーフローを防ぐための PHP の GC ガベージ処理メカニズムです。 PHP スレッドが終了すると、現在占有されているすべてのメモリ領域が破棄され、現在のプログラム内のすべてのオブジェクトが同時に破棄されます。 GC プロセスは通常、セッションごとに実行を開始します。 gc の目的は、セッション ファイルが期限切れになった後に自動的に破棄して削除することです。 2. __destruct /unset __destruct() ガベージ オブジェクトがリサイクルされるときにデストラクターが実行されます。
unset は、オブジェクトではなく、オブジェクトを指す変数を破棄します。 3. セッションと PHP のガベージ コレクション メカニズム PHP の動作メカニズムにより、セッション情報を定期的にスキャンしてセッション情報が無効かどうかを判断するデーモン スレッドがありません。有効なリクエストが発生した場合、PHP はグローバル変数 session.gc_probability を使用します。デフォルトでは、session.gc_probability=1、session.gc_pisor =100 は、GC が開始される可能性が 1% であることを意味します (つまり、GC は 100 個に 1 つだけです)。 PHP ガベージ コレクション メカニズムの仕事は、すべてのセッション情報をスキャンし、現在の時刻からセッションの最終変更時刻を減算し、それを session.gc_maxlifetime パラメーターと比較することです。生存時間が gc_maxlifetime (デフォルトは 24 分) を超えると、セッションは削除されます。
ただし、Web サーバーに複数のサイトがある場合、GC がセッションを処理するときに予期しない結果が発生する可能性があります。その理由は、GC が動作しているときに、異なるサイトのセッションが区別されないためです。
1. session.save_path を変更するか、session_save_path() を使用して各サイトのセッションを専用のディレクトリに保存します。
2. GC の起動率が向上します。システムのパフォーマンスもそれに応じて低下するため、推奨されません。
3. コード内の現在のセッションの有効期間を確認し、session_destroy() を使用して削除します。


参照カウントの基礎知識
各 PHP 変数は、「zval」と呼ばれる変数コンテナーに存在します。zval 変数コンテナーには、変数の型と値に加えて、2 バイトの追加情報も含まれています。 1 つ目は「is_ref」です。これは、この変数が参照セットに属しているかどうかを識別するために使用されるブール値です。PHP では、ユーザーがカスタム参照を使用できるため、このバイトを通じて通常の変数と参照変数を区別できます。 zval 変数コンテナには、メモリ使用量を最適化するための内部参照カウント メカニズムがあります。2 番目の追加バイトは「refcount」で、この zval 変数コンテナ Number を指す変数 (シンボルとも呼ばれます) を表すために使用されます。変数に定数値が割り当てられると、次の例に示すように、zval 変数コンテナーが生成されます。

  <?php 
      $a = "new string"; 
  ?>


上記の例では、新しい変数は a で、現在の変数で Generated にあります。また、追加の 2 バイトの情報では、「refcount」が 1 に設定されているため、「is_ref」が false に設定されます。この変数コンテナを使用する変数は 1 つだけであるため、xdebug を呼び出して変数の内容を表示します。


  <?php 
      $a = "new string";
      xdebug_debug_zval(&#39;a&#39;); 
  ?>


上記のコードは次のように出力します。変数 a


  a: (refcount=1, is_ref=0)=&#39;new string&#39;


上記のコードは次のように出力します:


  <?php 
      $a = "new string"; 
      $b = $a; 
      xdebug_debug_zval(&#39;a&#39;); 
  ?>


このとき、同じ変数コンテナが変数 a によって使用されているため、参照の数は 2 になります。変数 b を使用すると、PHP は生成された変数コンテナを必要のない場合にコピーしません。変数コンテナは、「refcount」が 0 になると破棄されます。変数に関連付けられた変数がそのスコープを離れると (例: 関数の実行が終了します)、または、変数に対して unset() 関数が呼び出されると、「refcount」が 1 減ります。次の例で説明します。


  a: (refcount=2, is_ref=0)=&#39;new string&#39;


上記のコードは出力します。ここで unset($a) を実行すると、 $ の型と値を含むコンテナがメモリから削除されます


複合型(複合型)


array や object のような複合型を考慮すると、もう少し複雑になります。スカラー型の値とは異なり、配列およびオブジェクト型の変数は、そのメンバーまたはプロパティを独自のシンボル テーブルに格納します。これは、次の例では 3 つの zval 変数コンテナーを生成することを意味します。
<?php 
  $a = array(&#39;meaning&#39; => &#39;life&#39;, &#39;number&#39; => 42);
  xdebug_debug_zval(&#39;a&#39;); 
?>

以上代码输出:


  a: (refcount=1, is_ref=0)=array (&#39;meaning&#39; => (refcount=1, is_ref=0)=&#39;life&#39;, &#39;number&#39; => (refcount=1, is_ref=0)=42)

这三个zval变量容器是:a,meaning,number.增加和减少refcount的规则和上面提到的一样


特例,添加数组本身作为数组元素时:


<?php 
  $a = array(&#39;one&#39;); 
  $a[] = &$a; 
  xdebug_debug_zval(&#39;a&#39;); 
?>

以上代码输出的结果:


  a: (refcount=2, is_ref=1)=array (0 => (refcount=1, is_ref=0)=&#39;one&#39;, 1 => (refcount=2, is_ref=1)=...)

可以看到数组a和数组本身元素a[1]指向的变量容器refcount为2

当对数组$a调用unset函数时,$a的refcount变为1,发生了内存泄漏

清理变量容器的问题
尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),由于数组元素"1"仍然指向数组本身,所以这个容器不能被消除.因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏.庆幸的是,php将在请求结束时清除这个数据结构,但是php清除前,将耗费不少内存空间


回收周期
5.3.0PHP使用了新的同步周期回收算法,来处理上面所说的内存泄漏问题

首先,我们先要建立一些基本规则:
如果一个引用计数增加,它将继续被使用,当然就不再垃圾中.如果引用技术减少到零,所在的变量容器将被清除(free).就是说,仅仅在引用计数减少到非零值时,才会产生垃圾周期(grabage cycle).其次,在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾

2015810114143348.png (429×552)

为避免不得不检查所有引用计数可能减少的垃圾周期,这个算法把所有可能根(possible roots 都是zval变量容器),放在根缓冲区(root buffer)中(用紫色标记),这样可以同时确保每个可能的垃圾根(possible garbage root)在缓冲区只出现一次.仅仅在根缓冲区满了时,才对缓冲区内部所有不同的变量容器执行垃圾回收操作。

相关推荐:

php底层分析的视频和课件分享

浅析PHP底层的运行机制和工作原理

PHP底层工作原理_PHP教程


以上がPHPにおけるGCの仕組みを詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。