>백엔드 개발 >PHP 튜토리얼 >PHP 가비지 수집 메커니즘(gc) 소개

PHP 가비지 수집 메커니즘(gc) 소개

尚
앞으로
2020-03-27 09:17:132913검색

PHP 가비지 수집 메커니즘(gc) 소개

php 컴파일 원칙:

ze(zend 엔진)는 어휘 분석기를 호출하여 PHP 코드에서 공백을 제거하고 개별적으로 분할합니다. comments 토큰 뒤의 부분을 보면 ze는 구문 분석기를 호출한 후 토큰을 처리하여 opcode를 형성합니다. opcode는 op 배열 형태로 존재하며, ze는 최종적으로 op 배열을 실행하여 결과를 출력합니다.

PHP 스레드가 종료되면 현재 점유된 메모리 공간이 모두 소멸됩니다. 그렇다면 이 스레드가 끝나지 않으면 어떻게 메모리를 회수할 수 있을까요?

refcount: 컨테이너를 가리키는 포인터의 수로 이해할 수 있는 참조 기술 장치입니다.

is_ref: 참조 여부(0 또는 1만 가능)

할당 프로세스:

<?php

$a = &#39;aa&#39;;
   
xdebug_debug_zval(a);  //(refcount=1, is_ref=0),string &#39;aa&#39; (length=6)

$b = $a; 

//以下的两个其实是一个变量容器

xdebug_debug_zval(a); //(refcount=2, is_ref=0),string &#39;aa&#39; (length=6)
xdebug_debug_zval(b); //(refcount=2, is_ref=0),string &#39;aa&#39; (length=6)

unset($b);  //对变量容器 refcount 减1xdebug_debug_zval(a); //(refcount=1, is_ref=0),string &#39;aa&#39; (length=6)
xdebug_debug_zval(b); //b: no such symbol  b变量被销毁,指向被断掉,如果对应容器的引用技术为零,那么该块儿内存被回收


$b = $a;

$b = &#39;bb&#39;;

xdebug_debug_zval(a); //(refcount=1, is_ref=0),string &#39;aa&#39; (length=6)
xdebug_debug_zval(b); //(refcount=1, is_ref=0),string &#39;aa&#39; (length=6)  重新申请一个变量容器存储b,a的变量容器引用减1

견적 프로세스:

<?php

$a = &#39;aa&#39;;

xdebug_debug_zval(&#39;a&#39;);  //(refcount=1, is_ref=0),string &#39;aa&#39; (length=2)

$b = & $a;//变量容器的引用技术加1,引用标记置为1xdebug_debug_zval(&#39;a&#39;);  //(refcount=2, is_ref=1),string &#39;aa&#39; (length=2)
xdebug_debug_zval(&#39;b&#39;);  //(refcount=2, is_ref=1),string &#39;aa&#39; (length=2)


$b = &#39;123&#39;; 

//php会发现,该容器变量是引用(is_ref),所以容器变量不用像赋值那样再申请一个

xdebug_debug_zval(&#39;a&#39;);  //(refcount=2, is_ref=1),string &#39;123&#39; (length=2)
xdebug_debug_zval(&#39;b&#39;);  //(refcount=2, is_ref=1),string &#39;123&#39; (length=2)


unset($b);//变量容器应用计数减1,引用为零

xdebug_debug_zval(&#39;a&#39;);  //(refcount=1, is_ref=0),string &#39;123&#39; (length=2)
xdebug_debug_zval(&#39;b&#39;); // b: no such symbol

그러면 하나가 여러 번 참조되고 하나가 설정되지 않으면 is_ref가 0으로 설정되나요? 그러면 버그가 발생하지 않나요? 변수 컨테이너는 여전히 참조입니다. 그럼 한 번 살펴보겠습니다.

<?php


$a = &#39;aa&#39;;

$b = &$a;
$c = &$a;//可以看到引用refCount是3,is_ref永远是1xdebug_debug_zval(&#39;a&#39;); //(refcount=3, is_ref=1),string &#39;aa&#39; (length=2)
xdebug_debug_zval(&#39;b&#39;); //(refcount=3, is_ref=1),string &#39;aa&#39; (length=2)
xdebug_debug_zval(&#39;c&#39;); //(refcount=3, is_ref=1),string &#39;aa&#39; (length=2)


unset($b);//我们期待的bug没有出现,只是refcount减1,is_ref还是1xdebug_debug_zval(&#39;a&#39;); //(refcount=2, is_ref=1),string &#39;aa&#39; (length=2)
xdebug_debug_zval(&#39;b&#39;); // b: no such symbol
xdebug_debug_zval(&#39;c&#39;); //(refcount=2, is_ref=1),string &#39;aa&#39; (length=2)

//那php它怎么知道这个容器还有引用,毕竟is_ref仍然是1,不能计数,那么现在refcount就起作用了,是它告诉php,该变量有几个引用,但问题又来了,如果我干点坏事,在引用的时候,又赋值,它会不会有bug

$e = $a;//我们看到期望的bug还是没出现,这时候再赋值,就不像直接赋值那么简单refcount加1了,而是申请了一个新的变量容器

xdebug_debug_zval(&#39;a&#39;); //(refcount=2, is_ref=1),string &#39;aa&#39; (length=2)
xdebug_debug_zval(&#39;e&#39;); //(refcount=1, is_ref=0),string &#39;aa&#39; (length=2)

설정 해제 및 null 할당 모두 변수를 재활용할 수 있나요? 많은 사람들은 이 두 가지가 변수 공간을 재활용할 수 있다고 잘못 생각합니다. 실제로 null은 재활용 관점에서 볼 때 컨테이너가 차지하는 공간을 줄이는 것뿐입니다.

<?php

$a = &#39;aa&#39;;

$b = $a;

$b = null;

//又申请了一个变量容器
xdebug_debug_zval(&#39;a&#39;);  //(refcount=1, is_ref=0),string &#39;aa&#39; (length=2)
xdebug_debug_zval(&#39;b&#39;);  //(refcount=1, is_ref=0),null   变量空间并没被回收

unset($b);

//这时候才释放了b变量容器的空间
xdebug_debug_zval(&#39;a&#39;);  //(refcount=1, is_ref=0),string &#39;aa&#39; (length=2)
xdebug_debug_zval(&#39;b&#39;);  //b: no such symbol

추천: PHP 비디오 튜토리얼

위 내용은 PHP 가비지 수집 메커니즘(gc) 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 oschina.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제