이 글에서는 PHP 소스 코드 34에 대해 주로 소개합니다. PHP5.3에 새로 추가된 가비지 컬렉션 메커니즘은 이제 특정 참고 가치가 있어 도움이 필요한 모든 사람들과 공유합니다.
PHP 소스코드에 대해 간단히 이야기해보자 34: PHP5.3에 새로 추가된 가비지 컬렉션 메커니즘(Garbage Collection)
이전 글에서는 PHP 소스코드에 대해 이야기해보자. 33: PHP5.3의 새로운 가비지 수집 메커니즘(Garbage Collection) 기본에서는 가비지 수집 메커니즘에 대한 몇 가지 기본 지식을 소개합니다. 오늘 우리는 초기화를 살펴보고 가비지 버퍼와 가비지 수집 프로세스를 추가합니다.
공식 문서를 보려면 Garbage Collection을 클릭하세요
중국어 버전 주소: http://docs.php.net/manual/zh/features.gc.php
【초기화】#🎜 🎜# zend/zend_gc.c의 121번째 줄에는 gc의 초기화를 구현하는 gc_init 함수가 있습니다. 코드는 다음과 같습니다:
ZEND_API void gc_init(TSRMLS_D){ if (GC_G(buf) == NULL && GC_G(gc_enabled)) { GC_G(buf) = (gc_root_buffer*) malloc(sizeof(gc_root_buffer) * GC_ROOT_BUFFER_MAX_ENTRIES); GC_G(last_unused) = &GC_G(buf)[GC_ROOT_BUFFER_MAX_ENTRIES]; gc_reset(TSRMLS_C); }}123번째 줄은 비어 있는지, gc가 비어 있는지 여부를 결정합니다. 둘 다 true이면 124번째 줄로 이동합니다.
124번째 줄은 malloc을 직접 호출하여 10,000gc_root_buffer 메모리를 할당합니다.
Line 125는 전역 변수 last_unused를 gc 버퍼의 끝 위치로 설정합니다.
126행은 전체 가비지 수집 메커니즘을 재설정합니다. 코드는 다음과 같이 zend/zend_gc.c의 88행에서 시작합니다.
ZEND_API void gc_reset(TSRMLS_D){ GC_G(gc_runs) = 0; GC_G(collected) = 0; #if GC_BENCH GC_G(root_buf_length) = 0; GC_G(root_buf_peak) = 0; GC_G(zval_possible_root) = 0; GC_G(zobj_possible_root) = 0; GC_G(zval_buffered) = 0; GC_G(zobj_buffered) = 0; GC_G(zval_remove_from_buffer) = 0; GC_G(zobj_remove_from_buffer) = 0; GC_G(zval_marked_grey) = 0; GC_G(zobj_marked_grey) = 0;#endif GC_G(roots).next = &GC_G(roots); GC_G(roots).prev = &GC_G(roots); if (GC_G(buf)) { GC_G(unused) = NULL; GC_G(first_unused) = GC_G(buf); GC_G(zval_to_free) = NULL; } else { GC_G(unused) = NULL; GC_G(first_unused) = NULL; GC_G(last_unused) = NULL; }}90~91행은 GC 수의 통계를 설정합니다. 실행(gc_runs)되고 gc의 가비지(수집) 수는 0입니다.
106~107행은 이중 연결 리스트의 헤드 노드의 이전 노드와 다음 노드가 자신을 가리키도록 설정합니다.
구현 코드는 zend/zend.c의 93번째 라인에 다음과 같습니다:
STD_ZEND_INI_BOOLEAN("zend.enable_gc","1",ZEND_INI_ALL,OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)초기화 호출은 zend/zend.c의 79번째 라인에 있습니다
static ZEND_INI_MH(OnUpdateGCEnabled) /* {{{ */{ OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); if (GC_G(gc_enabled)) { gc_init(TSRMLS_C); } return SUCCESS;}#🎜🎜 #[가비지 버퍼 영역에 추가]Track PHP 소스 코드 zend/zend_execute_API.c 424
[_zval_ptr_dtor] -> [GC_ZVAL_CHECK_POSSIBLE_ROOT()] -> gc_zval_possible_root() ]#🎜 🎜#gc_zval_check_possible_root() 함수에서는 배열과 객체에 대해 가비지 수집 작업만 수행됩니다
gc_zval_possible_root 함수의 코드는 다음과 같습니다
ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC){ if (UNEXPECTED(GC_G(free_list) != NULL && GC_ZVAL_ADDRESS(zv) != NULL && GC_ZVAL_GET_COLOR(zv) == GC_BLACK) && (GC_ZVAL_ADDRESS(zv) < GC_G(buf) || GC_ZVAL_ADDRESS(zv) >= GC_G(last_unused))) { /* The given zval is a garbage that is going to be deleted by * currently running GC */ return; } if (zv->type == IS_OBJECT) { GC_ZOBJ_CHECK_POSSIBLE_ROOT(zv); return; } GC_BENCH_INC(zval_possible_root); if (GC_ZVAL_GET_COLOR(zv) != GC_PURPLE) { GC_ZVAL_SET_PURPLE(zv); if (!GC_ZVAL_ADDRESS(zv)) { gc_root_buffer *newRoot = GC_G(unused); if (newRoot) { GC_G(unused) = newRoot->prev; } else if (GC_G(first_unused) != GC_G(last_unused)) { newRoot = GC_G(first_unused); GC_G(first_unused)++; } else { if (!GC_G(gc_enabled)) { GC_ZVAL_SET_BLACK(zv); return; } zv->refcount__gc++; gc_collect_cycles(TSRMLS_C); zv->refcount__gc--; newRoot = GC_G(unused); if (!newRoot) { return; } GC_ZVAL_SET_PURPLE(zv); GC_G(unused) = newRoot->prev; } newRoot->next = GC_G(roots).next; newRoot->prev = &GC_G(roots); GC_G(roots).next->prev = newRoot; GC_G(roots).next = newRoot; GC_ZVAL_SET_ADDRESS(zv, newRoot); newRoot->handle = 0; newRoot->u.pz = zv; GC_BENCH_INC(zval_buffered); GC_BENCH_INC(root_buf_length); GC_BENCH_PEAK(root_buf_peak, root_buf_length); } }}#🎜 🎜#Lines 132~140 zval 매듭 확인 포인트 정보가 노드 버퍼에 들어갔는지 여부, 노드 버퍼에 넣었다면 직접 반환하여 성능을 최적화할 수 있음
Lines 142 ~145 객체 노드를 직접 처리하고 더 이상 후속 작업을 수행하지 않습니다.
149행은 노드가 보라색으로 표시되었는지 여부를 결정합니다. 이는 더 이상 노드 버퍼에 추가되지 않습니다. 노드가 버퍼 작업에 추가만 수행하는지 확인하는 것입니다.
150행은 노드의 색상을 보라색으로 표시하여 이 노드가 버퍼에 추가되었으며 다음에 추가할 필요가 없음을 나타냅니다.
알아보기 153~157번째 줄에는 새 노드의 위치입니다. 버퍼가 가득 차면 가비지 수집 작업이 수행됩니다.
176~184번째 줄은 버퍼가 위치한 이중 연결 리스트에 새로운 노드를 추가합니다.
[가비지 수집 프로세스]
gc_zval_possible_root 함수에서 버퍼가 가득 차면 프로그램은 gc_collect_cycles 함수를 호출하여 가비지 수집 작업을 수행합니다. zend/zend_gc.c 파일의 615번째 줄부터 구현 코드는 다음과 같습니다:ZEND_API int gc_collect_cycles(TSRMLS_D){ int count = 0; if (GC_G(roots).next != &GC_G(roots)) { zval_gc_info *p, *q, *orig_free_list, *orig_next_to_free; if (GC_G(gc_active)) { return 0; } GC_G(gc_runs)++; GC_G(zval_to_free) = FREE_LIST_END; GC_G(gc_active) = 1; gc_mark_roots(TSRMLS_C); gc_scan_roots(TSRMLS_C); gc_collect_roots(TSRMLS_C); orig_free_list = GC_G(free_list); orig_next_to_free = GC_G(next_to_free); p = GC_G(free_list) = GC_G(zval_to_free); GC_G(zval_to_free) = NULL; GC_G(gc_active) = 0; /* First call destructors */ while (p != FREE_LIST_END) { if (Z_TYPE(p->z) == IS_OBJECT) { if (EG(objects_store).object_buckets && EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid && EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0 && EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor && !EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called) { EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called = 1; EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount++; EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.object, Z_OBJ_HANDLE(p->z) TSRMLS_CC); EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount--; } } count++; p = p->u.next; } /* Destroy zvals */ p = GC_G(free_list); while (p != FREE_LIST_END) { GC_G(next_to_free) = p->u.next; if (Z_TYPE(p->z) == IS_OBJECT) { if (EG(objects_store).object_buckets && EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid && EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0) { EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1; Z_TYPE(p->z) = IS_NULL; zend_objects_store_del_ref_by_handle_ex(Z_OBJ_HANDLE(p->z), Z_OBJ_HT(p->z) TSRMLS_CC); } } else if (Z_TYPE(p->z) == IS_ARRAY) { Z_TYPE(p->z) = IS_NULL; zend_hash_destroy(Z_ARRVAL(p->z)); FREE_HASHTABLE(Z_ARRVAL(p->z)); } else { zval_dtor(&p->z); Z_TYPE(p->z) = IS_NULL; } p = GC_G(next_to_free); } /* Free zvals */ p = GC_G(free_list); while (p != FREE_LIST_END) { q = p->u.next; FREE_ZVAL_EX(&p->z); p = q; } GC_G(collected) += count; GC_G(free_list) = orig_free_list; GC_G(next_to_free) = orig_next_to_free; } return count;}619번째 줄은 버퍼가 비어 있는지 여부를 결정합니다. 비어 있으면 가비지 수집 작업이 수행되지 않습니다. 수행됨
622행은 가비지 수집 작업이 진행 중인지 확인합니다. 진행 중이면 직접 반환합니다.
625~627행 가비지 수집 작업 수에 1을 더하고 사용 가능 목록을 초기화한 후 설정합니다. gc_active를 1로 설정하여 가비지 반환이 진행 중임을 나타냅니다.
Line 629 이것이 알고리즘의 C단계입니다. 알고리즘은 다시 한번 각 루트 노드에 대해 깊이 우선 검색을 사용하고 참조 개수가 0이면 변수 컨테이너가 0보다 큰 경우 작업이 수행됩니다. 이 시점에서 깊이 우선 탐색을 사용하여 참조 카운트를 1씩 감소시키는 작업이 재개된 다음 참조 카운트가 1만큼 증가합니다.
라인 630의 알고리즘의 마지막 단계 D, 알고리즘이 순회합니다. 거기에서 변수 컨테이너 루트(zval 루트)를 제거하는 동시에 이전 단계에서 흰색으로 표시된 변수 컨테이너가 있는지 확인합니다. [gc_collect_cycles() -> gc_collect_roots() -> zval_collect_white() ]에서 흰색으로 표시된 노드가 전역 변수 zval_to_free 목록에 추가됩니다.
라인. 632~633 전역 변수 free_list 및 next_to_free를 해당 임시 변수에 저장하고 마지막에 현재 상태로 복원됩니다.
634~635행은 지워야 할 목록을 초기화하고 zval 목록을 지웁니다. 가비지 수집 작업 상태를 비활성 상태로 설정합니다.
639~655번째 줄은 소멸자를 처음으로 호출하고 지워진 변수의 수를 계산합니다.
657~678번째 줄의 변수 지우기#🎜🎜 # 682~686행 메모리 해제
687~689행은 가비지 번호 통계 처리 및 free_list 및 next_to_free 변수 복원# 🎜🎜#
위 내용은 이 글의 전체 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지를 주목해주세요
관련 추천:
PHP 소스 코드에 대한 간략한 토론 33: PHP5.3의 새로운 가비지 수집 메커니즘(가비지 수집)의 기본
PHP 소스 코드에 대한 간략한 토론 32: PHP의 emalloc/efree 레이어 및 힙 메모리 풀) 레이어
PHP 소스 코드 29에 대한 간략한 토론: 인터페이스 상속에 대하여
위 내용은 PHP 소스 코드 34에 대한 간략한 논의: PHP5.3에 새로 추가된 가비지 수집 메커니즘(Garbage Collection)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

PHP는 주로 절차 적 프로그래밍이지만 객체 지향 프로그래밍 (OOP)도 지원합니다. Python은 OOP, 기능 및 절차 프로그래밍을 포함한 다양한 패러다임을 지원합니다. PHP는 웹 개발에 적합하며 Python은 데이터 분석 및 기계 학습과 같은 다양한 응용 프로그램에 적합합니다.

PHP는 1994 년에 시작되었으며 Rasmuslerdorf에 의해 개발되었습니다. 원래 웹 사이트 방문자를 추적하는 데 사용되었으며 점차 서버 측 스크립팅 언어로 진화했으며 웹 개발에 널리 사용되었습니다. Python은 1980 년대 후반 Guidovan Rossum에 의해 개발되었으며 1991 년에 처음 출시되었습니다. 코드 가독성과 단순성을 강조하며 과학 컴퓨팅, 데이터 분석 및 기타 분야에 적합합니다.

PHP는 웹 개발 및 빠른 프로토 타이핑에 적합하며 Python은 데이터 과학 및 기계 학습에 적합합니다. 1.PHP는 간단한 구문과 함께 동적 웹 개발에 사용되며 빠른 개발에 적합합니다. 2. Python은 간결한 구문을 가지고 있으며 여러 분야에 적합하며 강력한 라이브러리 생태계가 있습니다.

PHP는 현대화 프로세스에서 많은 웹 사이트 및 응용 프로그램을 지원하고 프레임 워크를 통해 개발 요구에 적응하기 때문에 여전히 중요합니다. 1.PHP7은 성능을 향상시키고 새로운 기능을 소개합니다. 2. Laravel, Symfony 및 Codeigniter와 같은 현대 프레임 워크는 개발을 단순화하고 코드 품질을 향상시킵니다. 3. 성능 최적화 및 모범 사례는 응용 프로그램 효율성을 더욱 향상시킵니다.

phphassignificallyimpactedwebdevelopmentandextendsbeyondit

PHP 유형은 코드 품질과 가독성을 향상시키기위한 프롬프트입니다. 1) 스칼라 유형 팁 : PHP7.0이므로 int, float 등과 같은 기능 매개 변수에 기본 데이터 유형을 지정할 수 있습니다. 2) 반환 유형 프롬프트 : 기능 반환 값 유형의 일관성을 확인하십시오. 3) Union 유형 프롬프트 : PHP8.0이므로 기능 매개 변수 또는 반환 값에 여러 유형을 지정할 수 있습니다. 4) Nullable 유형 프롬프트 : NULL 값을 포함하고 널 값을 반환 할 수있는 기능을 포함 할 수 있습니다.

PHP에서는 클론 키워드를 사용하여 객체 사본을 만들고 \ _ \ _ Clone Magic 메소드를 통해 클로닝 동작을 사용자 정의하십시오. 1. 복제 키워드를 사용하여 얕은 사본을 만들어 객체의 속성을 복제하지만 객체의 속성은 아닙니다. 2. \ _ \ _ 클론 방법은 얕은 복사 문제를 피하기 위해 중첩 된 물체를 깊이 복사 할 수 있습니다. 3. 복제의 순환 참조 및 성능 문제를 피하고 클로닝 작업을 최적화하여 효율성을 향상시키기 위해주의를 기울이십시오.

PHP는 웹 개발 및 컨텐츠 관리 시스템에 적합하며 Python은 데이터 과학, 기계 학습 및 자동화 스크립트에 적합합니다. 1.PHP는 빠르고 확장 가능한 웹 사이트 및 응용 프로그램을 구축하는 데 잘 작동하며 WordPress와 같은 CMS에서 일반적으로 사용됩니다. 2. Python은 Numpy 및 Tensorflow와 같은 풍부한 라이브러리를 통해 데이터 과학 및 기계 학습 분야에서 뛰어난 공연을했습니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

WebStorm Mac 버전
유용한 JavaScript 개발 도구

드림위버 CS6
시각적 웹 개발 도구

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

안전한 시험 브라우저
안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.
