우리 모두는 PHP 변수가 약한 유형이므로 선언할 때 유형을 지정할 필요가 없다는 것을 알고 있습니다. 그렇다면 이것은 어떻게 구현됩니까? 이는 변수의 기본 구조부터 시작해야 합니다.
소스 코드 파일 zend_type.h에서 zval의 정의를 볼 수 있습니다.
typedef struct _zval_struct zval;struct _zval_struct { zend_value value; /* value */ union { struct { ZEND_ENDIAN_LOHI_4( zend_uchar type, /* active type */ zend_uchar type_flags, zend_uchar const_flags, zend_uchar reserved) /* call info for EX(This) */ } v; uint32_t type_info; } u1; union { uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* literal cache slot */ uint32_t lineno; /* line number (for ast nodes) */ uint32_t num_args; /* arguments number for EX(This) */ uint32_t fe_pos; /* foreach position */ uint32_t fe_iter_idx; /* foreach iterator index */ uint32_t access_flags; /* class constant access flags */ uint32_t property_guard; /* single property guard */ uint32_t extra; /* not further specified */ } u2; }复制代码
zval의 구조는 변수 유형의 값 또는 포인터를 저장하는 Union Union zend_value와 두 개의 Union Union으로 구성됩니다. u1과 u2는
u1로 구성되며, 변수 유형과 해당 정보를 저장하는 데 사용됩니다.
type: 변수 유형을 기록합니다. u2.v.type을 통해
type_flags에 액세스할 수 있습니다. 고유한 유형의 변수(예: 상수 유형, 참조 계산 유형, 불변 유형)에 해당하는 플래그입니다.
const_flags: 상수 유형 플래그
reserved: 예약된 필드
u2는 주로 보조 기능입니다. 구조의 메모리 정렬로 인해 u2가 있든 없든 u2의 공간이 이미 공간을 차지했습니다. , 그러니 활용해보세요. u2의 보조 필드는 많은 유형 정보를 기록하는데, 이는 내부 기능에 큰 이점을 주거나 캐시 친화성을 향상시키거나 메모리 주소 지정 작업을 줄입니다. 여기에는 이러한 필드 중 일부가 소개되어 있습니다.
next: 해시 충돌 문제(해시 충돌은 아직 이해되지 않음)를 해결하고 충돌의 다음 요소 위치를 기록하는 데 사용됩니다.
cache_slot: 런타임 캐시. 함수를 실행할 때 먼저 캐시에서 검색합니다. 캐시에서 찾을 수 없으면 전역 함수 테이블에서 검색합니다.
num_args: 함수 호출 시 전달되는 매개변수 수
access_flags: public protected private과 같은 객체 클래스의 액세스 플래그.
typedef union _zend_value { zend_long lval; /* 整型*/ double dval; /* 浮点型 */ zend_refcounted *counted; zend_string *str; zend_array *arr; zend_object *obj; zend_resource *res; zend_reference *ref; zend_ast_ref *ast; zval *zv; void *ptr; zend_class_entry *ce; zend_function *func; struct { uint32_t w1; uint32_t w2; } ww; } zend_value;复制代码
zend__value에서 볼 수 있듯이 long 및 double 유형은 값을 직접 저장하는 반면, 다른 유형은 해당 구조를 가리키는 포인터입니다. 따라서 zval의 구조로 인해 PHP 변수는 변수를 선언할 때 해당 유형을 명시적으로 지정할 필요가 없습니다. 변수에 할당한 값의 유형에 관계없이 해당 저장 구조를 찾는 데 도움이 될 수 있기 때문입니다.
문자열 값을 갖는 변수를 예로 들면 그 구조는 다음과 같습니다.
php7의 zval은 총 16바이트만 차지하여 PHP5의 48바이트인 zval에 비해 메모리가 많이 절약되는 것을 볼 수 있습니다.
또한 PHP5에서는 모든 변수가 힙에 할당되지만 임시 변수의 경우 힙에 할당할 필요가 없습니다. 따라서 이는 PHP7에서 최적화되었으며 임시 변수는 스택에 직접 적용됩니다.
다음은 몇 가지 일반적인 유형의 변수 구조를 소개합니다. 더 많은 유형에 대해서는 소스 코드를 직접 볼 수 있습니다.
정수 및 부동 소수점 유형의 경우 공간이 작기 때문에 정수 값은 zval에 직접 저장되고 lval에 저장되는 반면 부동 소수점 값은 dval에 저장됩니다.
typedef union _zend_value { zend_long lval; /* 整型*/ double dval; /* 浮点型 */ ... }复制代码
PHP 7에서는 새로운 문자열 구조가 정의되었습니다. 구조는 다음과 같습니다.
struct _zend_string { zend_refcounted_h ; zend_ulong h; /* hash value */ size_t len; char val[1]; };复制代码
위 각 필드의 의미:
gc: 변수 참조 정보, 참조 카운팅을 사용하는 모든 변수 유형은 이 구조를 갖습니다.
h: 배열의 인덱스를 계산할 때 사용되는 해시 값입니다. (이 작업을 수행하면 PHP7의 성능이 5% 향상된다고 합니다.)
len: 문자열 길이, 이 값을 통해 바이너리 보안이 보장됩니다.
val: 문자열 내용, 가변 길이 구조체, 실행 시 len 길이에 따라 메모리를 적용합니다. 할당 Array
array는 PHP의 매우 강력한 데이터 구조입니다. 기본 구현은 일반적인 정렬된 HashTable입니다. 자세한 내용은 나중에 설명하겠습니다.
typedef struct _zend_array HashTable;struct _zend_array { zend_refcounted_h gc; union { struct { ZEND_ENDIAN_LOHI_4( zend_uchar flags, zend_uchar nApplyCount, zend_uchar nIteratorsCount, zend_uchar consistency) } v; uint32_t flags; } u; uint32_t nTableMask; Bucket *arData; uint32_t nNumUsed; uint32_t nNumOfElements; uint32_t nTableSize; uint32_t nInternalPointer; zend_long nNextFreeElement; dtor_func_t pDestructor; }复制代码
###Objects
PHP7의 객체 구조도 재설계되었으며 이는 PHP5 구현과 매우 다릅니다.
struct _zend_object { zend_refcounted_h gc; uint32_t handle; zend_class_entry *ce; const zend_object_handlers *handlers; HashTable *properties; zval properties_table[1]; };复制代码
다음은 일부 필드입니다.
gc: gc 헤더
*ce: 개체에 해당하는 클래스
*properties: HashTable 구조, key는 개체의 속성 이름, value는 개체의 속성 값입니다. Properties_tables array 의 오프셋, 오프셋을 통해 Properties_talbe에서 해당 속성 값을 찾습니다.
properties_talbe[1]: 객체의 속성값을 저장합니다
무료 추천: PHP7
위 내용은 PHP7의 기본 변수를 마스터하세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!