>백엔드 개발 >PHP7 >PHP7 가비지 수집 메커니즘에 대한 자세한 설명(GC 처리의 전체 흐름도 포함)

PHP7 가비지 수집 메커니즘에 대한 자세한 설명(GC 처리의 전체 흐름도 포함)

藏色散人
藏色散人앞으로
2020-08-25 17:49:295088검색

가비지 컬렉션:

GC라고 합니다. 이름에서 알 수 있듯이 쓰레기를 재활용한다는 뜻이다.
가비지 수집 메커니즘에 대해 이야기하기 전에 먼저 메모리 누수에 대해 살펴보겠습니다.

추천 튜토리얼: "PHP7"

메모리 누수:

위대한 신의 그래픽 이미지 설명:

아마 땅을 신청하고 잠시 똥을 싸고 끝낸 후 치우지 않는다는 의미일 것입니다. 똥을 싸면 그 땅은 낭비되는 것으로 간주되며, 결국 그 땅은 똥으로 가득 차게 될 것입니다. 최종 분석 시에는 사용 후 꼭 반납해 주시기 바랍니다. 어느 정도 가비지 수집 메커니즘을 사용하여 엉덩이를 닦습니다.

C 언어 가비지 수집 메커니즘:

C 언어를 사용했다면 메모리를 적용하는 방법은 malloc 또는 calloc입니다. 그런 다음 이 메모리를 다 사용한 후에는 free 함수를 사용하여 해제하는 것을 잊지 마세요. 수동 가비지 수집은 일반적으로 마스터가 이런 방식으로 사용합니다.

PHP의 자동 가비지 수집 메커니즘은 무엇인가요?

먼저 이 질문에 대해 생각해 봅시다. PHP가 C 언어로 구현된다는 것은 우리 모두 알고 있습니다. C 언어를 사용하여 통계를 구현하고 변수를 해제하는 방법을 생각해 보세요. C 언어에서는 변수를 어떻게 구현하나요? 변수가 선언된 시점부터 아무도 사용하지 않는 시점까지 변수가 차지했던 메모리가 해제됩니다(가비지 수집).

PHP에는 메모리 관리를 위한 두 가지 핵심 알고리즘이 있습니다.
하나는 참조 계산이고 다른 하나는 쓰기 중 복사입니다.

PHP 변수를 선언할 때 C 언어는 맨 아래에 zval이라는 구조체(구조체)를 생성합니다.

zval {
string "a" //变量的名字是a
value zend_value //变量的值,联合体
type string //变量是字符串类型
}

zval struct 구조

(1) php $a
의 변수 이름을 저장합니다. (2) php의 변수 유형 $a
(3) php 변수 $a

의 zend_value 공용체 변수에 "hello world"와 같은 값을 지정하면 C 언어는 하단에 zend_value라는 공용체(union)를 생성합니다.

zend_value {
string "hello world" //值的内容
refcount 1 //引用计数
}

zend_value의 공용체(union)

(1) 다음의 값을 저장합니다. php $a hello world

(2) php $a 변수에 대한 참조 수를 기록하세요

zval 구조체 구조와 zend_value를 확인하세요. 면접관이 왜 php 변수가 문자열 "123"을 저장할 수 있는지 묻는다면. 그리고 123번은 어떻게 해야하는지 아시죠? 대답하셨나요? 중요한 점은 zval이 문자열 123이면 유형이 문자열이고 값이 정수 123이면 zval의 유형이 int이고 값이 포함된다는 것입니다. 123이다.

참조 카운팅이란 무엇인가요?

PHP 변수 참조 횟수의 코드 실제 ​​분석

$a = 'hello,world';
echo xdebug_debug_zval( 'a');//refcount=1
$b = $a;
echo xdebug_debug_zval( 'a'); //$b引用$a,故变量a,refcount=2
$c = $a;
echo xdebug_debug_zval( 'a'); //$c引用$a,故变量a,refcount=3
unset( $c );
echo xdebug_debug_zval( 'a');//删除了$c的引用,故变量a,refcount=2

실행 결과:

a:

(refcount=1, is_ref=0)string 'hello,world' (길이=11)
a:
(refcount=2 , is_ref=0)string 'hello,world' (길이=11)
a:
(refcount=3, is_ref=0)string 'hello,world' (길이=11)
a:
(refcount=2, is_ref = 0)문자열 'hello,world' (길이=11)

복사란 무엇인가요?

$a = 'hello';
$b = $a;//$a赋值给$b的时候,$a的值并没有真的复制了一份
echo xdebug_debug_zval( 'a');//$a的引用计数为2
$a = 'world';//当我们修改$a的值为123的时候,这个时候就不得已进行复制,避免$b的值和$a的一样
echo xdebug_debug_zval( 'a');///$a的引用计数为1

작업 결과:

a:

(refcount=2, is_ref=0)string 'hello' (length=5)
a:
(refcount=1, is_ref=0)string 'world' (length= 5)

사실 $a를 $b에 할당하면 $a의 값이 실제로 복사되지 않습니다. 이는 메모리에 매우 무례하며 시간 복잡도에 있어서도 매우 무례합니다. 컴퓨터는 단지 $를 가리킵니다. b를 $a의 값으로 변환하는 것이 빠르고 경제적입니다. 그렇다면 복제는 실제로 언제 발생합니까? 즉, $a의 값을 123으로 수정할 때, $b의 값이 $a와 동일해지는 것을 방지하기 위해 이때 복사를 해야 합니다.

참조 계산과 기록 중 복사라는 두 가지 핵심 사항이 간단한 사례를 통해 명확하게 설명됩니다.

가비지 수집 메커니즘:

zval이 설정되지 않거나 함수(즉, 로컬 변수) 및 기타 여러 위치에서 실행될 때 zval 및 zend_value의 연결이 끊어집니다. , zend 엔진이 감지해야 하는 것은 zend_value의 참조 횟수가 0인지 여부입니다. 0이면 콘텐츠를 직접 KO 해제합니다. zend_value의 재계산이 0이 아니면 값을 해제할 수 없지만 zend_value가 여전히 가비지일 수 있으므로 zend_value가 결백하다는 의미는 아닙니다.

(1) php 변수 $a의 참조 횟수가 0이면 $a 변수는 가비지 수집됩니다

(2) php 변수 $a>0의 참조 횟수이면 $a 변수도 고려할 수 있습니다. 쓰레기

어떤 상황에서 zend_value의 참조 횟수가 0이 아닌데 이 zend_value가 쓰레기가 될까요?

$arr = [ 1 ];
$arr[] = &$arr;
unset( $arr );

这种情况下,zend_value不会能释放,但也不能放过它,不然一定会产生内存泄漏,所以这会儿zend_value会被扔到一个叫做垃圾回收堆中,然后zend引擎会依次对垃圾回收堆中的这些zend_value进行二次检测,检测是不是由于上述两种情况造成的refcount为1但是自身却确实没有人再用了,如果一旦确定是上述两种情况造成的,那么就会将zend_value彻底抹掉释放内存。

垃圾回收发生在什么时候?

有些同学可能有疑问,就是php不是运行一次就销毁了吗,我要gc有何用?并不是的,首先当一次fpm运行完毕后,最后一定还有gc的,这个销毁就是gc;其次是,内存都是即用即释放的,而不是攒着非得到最后,你想想一个典型的场景,你的控制器里的某个方法里用了一个函数,函数需要一个巨大的数组参数,然后函数还需要修改这个巨大的数组参数,你们应该是函数的运行范围里面修改这个数组,所以此时会发生写时拷贝了,当函数运行完毕后,就得赶紧释放掉这块儿内存以供给其他进程使用,而不是非得等到本地fpm request彻底完成后才销毁。

(1)fpm运行完毕后,最后一定会gc的
(2)运行过程中,也会gc的,内存都是即用即释放的,而不是攒着非得到最后gc

GC处理完整流程图

 

위 내용은 PHP7 가비지 수집 메커니즘에 대한 자세한 설명(GC 처리의 전체 흐름도 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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