PHP 의 쓰레기 회수 메커니즘 분석

C 언어 를 사용 한 적 이 있다 면 메모 리 를 신청 하 는 방식 은 malloc 나 calloc 입 니 다.그리고 이 메모 리 를 다 사용 한 후에 free 함수 로 방출 하 는 것 을 잊 지 마 세 요.이것 이 바로 전설 속 수 동 쓰레기 회수 입 니 다.보통 청소 신 승 들 이 이런 방식 을 사용 합 니 다.많은 고 차원 언어 에서 당신 은 평생 메모리 관 리 를 접 하지 못 했 습 니 다.예 를 들 어 세계 에서 가장 좋 은 언어 phop,이런 언어 는 당신 을 위해 메모리 관 리 를 했 습 니 다.당신 은 마음 을 안정 시 키 고 나 쁜 코드 를 쓰 면 됩 니 다.php 를 썼 습 니 다.메모리 에 관심 이 있다 고 했 습 니 다.저 는 별로 믿 지 않 습 니 다.분명히 당신 이 강요 하고 있 는 것 입 니 다.물론 swoole 이나 wm 또는 자신 이 발명 한 상주 메모리 급 phop 애플 리 케 이 션 을 사용한다 면 메모리 유출 문제 에 관심 을 가 져 야 합 니 다.즉,무용 변 수 를 방출 하 는 것 을 기억 해 야 합 니 다.그렇다면 가장 보편적 이 고 전통 적 인 웹 개발 에서 phop 의 자동 쓰레기 회수 체 제 는 어 떨 까?이 문 제 는 우리 가 먼저 이렇게 생각 하 는 것 은 phop 이 C 언어 로 이 루어 진 것 을 알 고 있다 는 것 이다.지금 은 C 언어 를 여기에 두 었 다.그리고 C 언어 로 하나의 변수 에 대한 통계 와 방출 을 어떻게 실현 하 는 지 생각해 보 자.phop 을 어떻게 실현 할 지 생각 하지 마 세 요.C 언어 가 변 수 를 어떻게 실현 할 지 생각 하 세 요.성명 부터 마지막 까지 아무 도 사용 하지 않 으 면 이 변수 가 차지 하 는 메모 리 를 방출 합 니 다.너 는 이런 각도 에서 출발 하면 좀 편안 해 질 것 이다.이것 은 더 이상 기술적 인 문제 가 아니 라 바보 같이 제품 매니저 에 게 요구 하 는 바보 같은 수요 이다.자,본론 으로 들 어가 서 PHP 에서 메모리 관 리 를 하 는 핵심 알고리즘 은 모두 두 가지 입 니 다.하 나 는 인용 계수 이 고,다른 하 나 는 쓸 때 복사 하 는 것 입 니 다.PHP 변 수 를 설명 할 때 C 언어 는 밑 에 zval 이라는 struct(구조 체)를 만들어 줍 니 다.만약 당신 이 이 변수 에 값 을 부여 했다 면,예 를 들 어"hello World",그러면 C 언어 는 밑바닥 에서 다시 당신 에 게 zend 라 는 것 을 만들어 줄 것 입 니 다.value 의 유 니 온(연합 체)은 전체적으로 보면 이렇다.
자,코드 실전 단계 에 들 어가 서 두 가 지 를 주의 하 세 요.

$a = 'hello'. mt_rand( 1, 1000 );
echo xdebug_debug_zval( 'a');
$b = $a;
echo xdebug_debug_zval( 'a');
$c = $a;
echo xdebug_debug_zval( 'a');
unset( $c );
echo xdebug_debug_zval( 'a');
출력 결 과 는:

그 중에서 zval struct 구조 체 는$a,zend 를 저장 하 는 데 사 용 됩 니 다.value union 연합 체 는 데이터 내용 을 저장 하 는 데 사용 되 는'hello 916'이다.뒤에 b 와 c 가 성명 되 었 기 때문에 C 는 어 쩔 수 없 이 밑바닥 에서 두 개의 zval struct 구조 체 를 만들어 야 한다.
그 중에서 zval 과 zend value 의 구 조 는 다음 과 같다.(주의!!!이것 은 정확 한 PHP zval 과 zend 가 아 닙 니 다.value 는 C 언어 에서 struct 와 union 이 실현 되 었 습 니 다.단지 가장 중점 적 인 부분 을 골 라 서 썼 을 뿐 입 니 다.강조 하 세 요:zval 과 zend 를 한 글자 도 틀 리 지 않 고 외 울 필요 가 없습니다.value,너 는 원리 만 알 아야 한다)
zval {
string"a"/변수의 이름 은 a 입 니 다.
value zend_value//변수의 값
type string/변 수 는 문자열 형식 입 니 다.
}
zend_value {
string"hello 916"//값 의 내용
refcount 1//인용 계수
}
위의 두 가 지 를 보면 면접 관 이 phop 변 수 를 왜 저장 할 수 있 느 냐 고 물 으 면'123'도 숫자 123 을 저장 할 수 있 습 니 다.어떻게 대답 해 야 하 는 지 아 시 죠?중점 zval 에 이 변수 가 있 는 유형 을 대답 합 니 다.문자열 123 일 때 type 은 string 입 니 다.이때 value 는"123"을 가리 키 고 있 습 니 다.정수 123 일 때 zval 의 type 은 int 이 고 value 는 123 입 니 다.이것 이 바로 문 제 를 푸 는 사상 이다.이것 은 매우 중요 하 다!그리고 C 언어 를 통 해서 도 가능 합 니 다!구체 적 인 진짜 val 과 zendvalue 의 모습,관심 있 는 학생 들 은 인터넷 에서 검색 할 수 있 습 니 다.만약 당신 이 C 언어의 기초 가 없다 면 비교적 힘 들 것 입 니 다!전 자 는 struct 구조 체 이 고 후 자 는 유 니 온 연합 체 입 니 다!
이 refcount 는 전설 속 의 인용 계수 입 니 다.초기 화 할 때 a 뒤의 인용 횟수 는 1 입 니 다.value 인용 수 는 a 라 는 변수 zval 자체 가 아 닌 1 입 니 다.그리고 우 리 는$b=$a 를,사실은 또 하나의 변수 가 이 zend 를 가리 키 는 것 과 같다.value,그래서 refcount 를 2 로 바 꾸 고 마지막 으로$c=$a,동 리,zendvalue 의 refcount 가 1 을 더 하면 3 이 됩 니 다.그리고 우 리 는 unset($c)를 사용 합 니 다.지금 C 언어 로 해 야 할 일 은$c 의 zval 을 KO free 에 게 주 는 것 입 니 다.하지만 free zend 는 아 닙 니 다.value,지금 zendvalue 의 refcount 는 자 연 스 럽 게 1 을 줄 이 고 2 가 된다.
그럼 복사 할 때 무슨 뜻 이에 요?다음 코드 보기:

<?php
//           mt_rand,  ,       ,     
$a = 'hello'. mt_rand( 1, 1000 );
$b = $a;
$a = 123;
echo $b. PHP_EOL;
//운행 결과,내 가 말 하지 않 아 도 발가락 은'hello'.mt'인 거 다 알 아.rand(1,1000)의 결 과 는 절대 123 일 수 없습니다.
사실,$a 를$b 에 할당 할 때$a 의 값 은 실제로 복사 되 지 않 았 습 니 다.이것 은 메모리 에 대한 극도 의 존중 도,시간 복잡 도 에 대한 극도 의 존중 도 입 니 다.컴퓨터 는$b 를$a 의 값 으로 가리 키 는 것 일 뿐 입 니 다.이것 을 얼마나 빠 른 것 이 라 고 합 니 다.그렇다면 언제 진짜 복제 가 일어 날 까?$a 의 값 을 123 으로 수정 할 때$b 의 값 이$a 와 같 지 않도록 복사 할 수 밖 에 없습니다.

<?php
$a = 'hello'. mt_rand( 1, 1000 );
$b = $a;
echo xdebug_debug_zval( 'a');
$a = 'world'. mt_rand( 2, 2000 );
echo xdebug_debug_zval( 'a');
//운행 결 과 는 1 이 며,그 원 리 는 스스로 정리 할 수 있 을 것 이다.
이렇게 긴 이 야 기 를 하면 서 간단 한 사례 를 통 해 두 가지 요점 을 설명 했다.인용 계수 와 쓸 때 복사 하면 쓰레기 회수 도 와 야 한다.zval 이 unset 에 의 해 실 행 될 때,또는 한 함수 에서 실 행 될 때(즉 부분 변수)등 여러 곳 에서 zval 과 zend 가 발생 합 니 다.value 가 끊 기 는 행위 가 발생 했 습 니 다.이때 zend 엔진 이 감지 해 야 할 것 은 zend 입 니 다.value 의 refcount 가 0 인지,0 이면 KO free 로 내용 을 비 웁 니 다.하면,만약,만약...value 의 recount 는 0 이 아 닙 니 다(쓸데없는 말 은 0 이상 일 것 입 니 다).이 value 는 풀 려 날 수 없 지만 이 zend 를 대표 하 는 것 도 아 닙 니 다.value 는 결백 합 니 다.이 zendvalue 는 여전히 쓰레기 일 수 있 습 니 다.
어떤 상황 이 zendvalue 의 refcount 는 0 이 아니 지만,이 zendvalue 는 쓰레기 인 데?PHP 7 의 두 가지 상황:

<?php
$arr = [ 1 ];
$arr[] = &$arr;
unset( $arr );
이런 상황 에서 zendvalue 는 방출 할 수 없 지만 놓 쳐 서 는 안 됩 니 다.그렇지 않 으 면 메모리 누 출 이 발생 할 수 있 습 니 다.그래서 지금 zendvalue 는 쓰레기 수 거 더미 에 버 려 지고 zend 엔진 은 쓰레기 수 거 더미 에 있 는 zendvalue 는 2 차 검 사 를 실시 합 니 다.상기 두 가지 상황 으로 인 한 refcount 는 1 이지 만 자신 은 더 이상 사용 하지 않 습 니 다.상기 두 가지 상황 으로 인 한 것 이 확실 하 다 면 zendvalue 메모리 방출 을 철저히 지 웁 니 다.
그럼 쓰레기 수 거 는 언제 발생 합 니까?어떤 학우 들 은 의문 이 있 을 수 있 습 니 다.바로 phop 이 한 번 운행 하면 소각 되 지 않 습 니까?제 가 gc 를 원 하면 무슨 소 용이 있 습 니까?아 닙 니 다.먼저 fpm 가 실 행 된 후에 마지막 에 gc 가 있 을 것 입 니 다.이 소각 은 gc 입 니 다.그 다음 에 메모 리 는 모두 사용 하면 바로 방출 되 는 것 이지 마지막 을 얻 지 못 하 는 것 이 아 닙 니 다.전형 적 인 장면 을 생각해 보 세 요.컨트롤 러 안의 어떤 방법 에서 함 수 를 사 용 했 습 니 다.함 수 는 커 다란 배열 매개 변 수 를 필요 로 합 니 다.그리고 함 수 는 이 커 다란 배열 매개 변 수 를 수정 해 야 합 니 다.함수 의 운행 범위 에서 이 배열 을 수정 해 야 합 니 다.그래서 이 때 는 쓰기 시 복사 가 발생 합 니 다.함수 가 실 행 된 후에 이 메모 리 를 빨리 방출 하여 다른 프로 세 스 에 사용 하도록 해 야 합 니 다.로 컬 fpm request 가 완 료 된 후에 야 소각 하지 않 아 도 됩 니 다.
마지막 으로 자신의 말 을 하 세 요.대부분 상황 에서 면접 관 이 당신 에 게 문 제 를 묻 는 것 은 주로 생각 하 는 것 이 고 다른 하 나 는 당신 이 공부 하 는 정 도 를 보 는 것 입 니 다.gc 문제 와 같이 많은 스 크 립 트 언어의 쓰레기 회수 체 제 는 기본적으로 인용 계수 와 쓰기 시 복사 하 는 두 가지 알고리즘 을 결합 하여 이 루어 졌 기 때문에 스 크 립 트 언어 를 설계 하면 gc 체 제 는 이 두 가지 알고리즘 에 따라 디자인 하면 됩 니 다.그 다음으로 대부분의 phoper 는 이런 것들 을 보지 않 습 니 다.면접 관 이 당신 에 게 이 문 제 를 묻 는 것 은 당신 이 그렇게 많은 세부 사항 을 억지로 외 우 는 것 이 아니 라 당신 이 외 울 수 없 는 것 입 니 다.그 는 평소에 더욱 적극적으로 심층 으로 발전 하 는 마음 이 있 는 지 알 고 싶 습 니 다.
중점 을 나타 내 는 것 을 중시 하고 많은 세부 사항 을 쓸 수 없습니다.예 를 들 어 제 가 예 를 들 어$a=[],xdebugdebug_zval($a)의 refcount 값 은 얼마 일 까요?7.1.17 대 에 2 라 니,너 는 1 이 라 고 생각 하지만 그렇지 않다.그러나 이런 세부 사항 을 고민 하지 않 아 도 됩 니 다.gc 의 관건 은 인용 계수 의 원리 와 복사 할 때 복사 하 는 것 입 니 다.많은 세부 사항 깊 은 곳 에 각종 기괴 한 것들 이 있 습 니 다.면접 관 자신 도 모 릅 니 다.
이상 은 PHP 의 쓰레기 회수 메커니즘 에 대한 상세 한 내용 입 니 다.더 많은 PHP 의 쓰레기 회수 메커니즘 에 관 한 자 료 는 우리 의 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기