>  기사  >  백엔드 개발  >  PHP의 GC 메커니즘에 대한 자세한 설명

PHP의 GC 메커니즘에 대한 자세한 설명

*文
*文원래의
2017-12-27 14:12:384326검색

이 기사에서는 주로 PHP의 가비지 수집 메커니즘에 대한 해석을 소개합니다. GC 기능이 있는지 여부는 프로그래밍 언어 개발에 있어서 중요한 관심사입니다. 그것이 모두에게 도움이 되기를 바랍니다.

PHP의 기본 GC 개념
PHP 언어에도 다른 언어와 마찬가지로 가비지 수집 메커니즘이 있습니다. 그래서 오늘 우리가 여러분에게 설명하고 싶은 것은 PHP 가비지 수집 메커니즘과 관련이 있습니다. 그것이 모두에게 도움이 되기를 바랍니다. PHP strtotime 애플리케이션 경험 PHP memory_get_usage() 메모리 관리 PHP 설정되지 않은 전역 변수 사용 문제에 대한 자세한 설명 PHP unset() 함수는 변수를 파괴하여 PHP 전체 사이트 권한 확인을 신속하게 구현하는 방법을 알려줍니다. 1. PHP 가비지 수집 메커니즘(가비지 수집기, 참조) GC로) PHP에서 이 개체를 가리키는 변수가 없으면 이 개체는 가비지가 됩니다. PHP는 메모리에서 이를 파괴합니다. 이는 메모리 오버플로를 방지하기 위한 PHP의 GC 가비지 처리 메커니즘입니다. PHP 스레드가 종료되면 현재 점유된 모든 메모리 공간이 소멸되고, 현재 프로그램의 모든 객체도 동시에 소멸됩니다. GC 프로세스는 일반적으로 각 SESSION에서 실행을 시작합니다. gc의 목적은 세션 파일이 만료된 후 자동으로 삭제하고 삭제하는 것입니다. 2. __destruct /unset __destruct() 소멸자는 가비지 개체가 재활용될 때 실행됩니다.
unset은 객체가 아닌 객체를 가리키는 변수를 파괴합니다. 3. 세션 및 PHP 가비지 수집 메커니즘 PHP의 작동 메커니즘으로 인해 세션 정보를 정기적으로 검사하고 유효한 요청이 발생하면 PHP는 전역 변수 session.gc_probability를 사용합니다. session .gc_pisor의 값은 GC 활성화 여부를 결정합니다. 기본적으로 session.gc_probability=1, session.gc_pisor =100은 GC를 시작할 가능성이 1%라는 의미입니다(즉, 100번에 1번의 gc만 있음). 요청) 100개 요청 중 하나로 시작됩니다.) PHP 가비지 수집 메커니즘의 작업은 모든 세션 정보를 스캔하고 현재 시간에서 세션의 마지막 수정 시간을 뺀 후 이를 session.gc_maxlifetime 매개변수와 비교하는 것입니다. .생존 시간이 gc_maxlifetime(기본값 24분)을 초과하면 세션이 삭제됩니다.
그러나 웹 서버에 여러 사이트가 있는 경우 GC가 세션을 처리할 때 예상치 못한 결과가 발생할 수 있습니다. 그 이유는 GC가 작동할 때 다른 사이트의 세션을 구분하지 못하기 때문입니다. 그렇다면 이 문제를 어떻게 해결해야 할까요?
1. session.save_path()를 사용하여 각 사이트의 세션을 전용 디렉터리에 저장합니다.
2. 당연히 PHP 가비지 수집 메커니즘의 시작 속도가 증가합니다. 그에 따라 시스템 성능도 향상되지만 권장되지 않습니다.
3. 코드에서 현재 세션의 수명을 확인하고 session_destroy()를 사용하여 삭제합니다.


참조 계산에 대한 기본 지식
각 PHP 변수는 "zval"이라는 변수 컨테이너에 존재하며 변수의 유형과 값을 포함하는 것 외에도 2바이트의 추가 정보도 포함합니다. 첫 번째는 이 변수가 참조 세트에 속하는지 여부를 식별하는 데 사용되는 부울 값인 "is_ref"입니다. PHP에서는 사용자가 사용자 정의 참조를 사용할 수 있으므로 이 바이트를 통해 일반 변수와 참조 변수를 구분할 수 있습니다. zval 변수 컨테이너에는 메모리 사용을 최적화하기 위한 내부 참조 계산 메커니즘이 있습니다. 두 번째 추가 바이트는 이 zval 변수 컨테이너 번호를 가리키는 변수(기호라고도 함)를 나타내는 데 사용되는 "refcount"입니다.

변수에 상수 값이 할당되면 다음 예와 같이 zval 변수 컨테이너가 생성됩니다.


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



위 예에서 새 변수는 현재 생성된 a에 있습니다. 그리고 추가 2바이트 정보에서 "refcount"가 1로 설정된 사용자 정의 참조가 없기 때문에 "is_ref"는 기본적으로 false로 설정됩니다. , 이 변수 ​​컨테이너를 사용하는 변수는 하나만 있기 때문입니다. 변수 내용을 보려면 xdebug를 호출하세요.


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



위 코드는 다음을 출력합니다.


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



참조 횟수 추가 to 변수 a


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



위의 코드는 다음과 같이 출력됩니다.


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



이 때 변수 a가 동일한 변수 컨테이너를 사용하므로 참조 수는 2개입니다. 변수 b와 연관됨. PHP는 필요하지 않은 경우 생성된 변수 컨테이너를 복사하지 않습니다. "refcount"가 0이 되면 변수 컨테이너가 삭제됩니다. 변수와 연관된 변수가 해당 범위를 벗어나면(예: 함수 실행이 종료됩니다.) , 또는 unset() 함수가 변수에 대해 호출되면 "refcount"가 1만큼 감소합니다. 다음 예를 통해 설명할 수 있습니다.


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



위 코드는 다음을 출력합니다.


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

이제 unset($a)를 실행하면 $에 있는 유형과 값을 포함하는 컨테이너가 메모리에서 삭제됩니다

복합 유형(복합 유형)

배열 및 객체와 같은 복합 유형을 고려할 때 상황은 약간입니다. 더 복잡합니다. 스칼라 유형 값과 달리 배열 및 객체 유형 변수는 해당 멤버 또는 속성을 자체 기호 테이블에 저장합니다. 즉, 다음 예제에서는 세 개의 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.