다음 방법은 얼마나 많은 메모리를 차지합니까?
list($appid,$openid) = ["testcontent","test"];
Test
$m0 = memory_get_usage(); $k = range(1,200000); $m1 = memory_get_usage(); echo round(($m1-$m0)/pow(1024,2),4) ."MB\n"; foreach ($k as $i){ $n1 = "kk$i"; $n2 = "tt$i"; list($$n1,$$n2) = [$i,$i*3]; } $m2 = memory_get_usage(); echo round(($m2-$m1)/pow(1024,2),4) ."MB\n"; $m1 = memory_get_usage(); foreach ($k as $i){ $n1 = "kk$i"; $n2 = "tt$i"; $$n1 = $i+time(); $$n2 = 2*time(); } $m2 = memory_get_usage(); echo round(($m2-$m1)/pow(1024,2),4) ."MB\n";
위 연산의 출력 결과는 다음과 같습니다.
27.9404MB 51.3041MB 9.1553MB
어레이가 차지하는 메모리가 일반적으로 할당된 콘텐츠보다 훨씬 크다는 것을 알 수 있습니다
Principle
In PHP는 숫자를 표현하기 위해 long 타입을 사용하고 int 타입은 없습니다. PHP는 변수 유형을 구별하지 않으며 int float char *와 같은 개념이 없습니다. PHP가 zend에 저장하는 변수를 살펴보겠습니다. PHP의 각 변수에는 해당 zval이 있습니다. Zval 구조는 Zend/zend.h에 정의되어 있습니다.
typedef struct _zval_struct zval; struct _zval_struct { /* Variable information */ zvalue_value value; /* The value 1 12字节(32位机是12,64位机需要8+4+4=16) */ zend_uint refcount__gc; /* The number of references to this value (for GC) 4字节 */ zend_uchar type; /* The active type 1字节*/ zend_uchar is_ref__gc; /* Whether this value is a reference (&) 1字节*/ };
PHP는 변수를 저장하기 위해 UNION 구조를 사용합니다. 즉, zvalue_value는 공용체이며 UNION 변수가 차지하는 메모리는 최대 멤버 데이터 공간에 따라 결정됩니다.
typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { /* string value */ char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; /*object value */ } zvalue_value;
가장 큰 멤버 데이터 공간은 struct str이고, 포인터는 *val에 대해 4바이트를 차지하고, INT는 4바이트를 차지하여 총 8바이트입니다.
struct zval은 8+4+1+1 = 14바이트를 차지합니다. 실제로 zval의 배열, 문자열 및 개체에는 Zend/zend_hash.h에 정의된 HashTable:
HashTable 구조가 필요합니다.
typedef struct _hashtable { uint nTableSize;//4 uint nTableMask;//4 uint nNumOfElements;//4 ulong nNextFreeElement;//4 Bucket *pInternalPointer; /* Used for element traversal 4*/ Bucket *pListHead;//4 Bucket *pListTail;//4 Bucket **arBuckets;//4 dtor_func_t pDestructor;//4 zend_bool persistent;//1 unsigned char nApplyCount;//1 zend_bool bApplyProtection;//1 #if ZEND_DEBUG int inconsistent;//4 #endif } HashTable;
HashTable 구조에는 39바이트가 필요하며 각 배열 요소는 Bucket 구조에 저장됩니다.
typedef struct bucket { ulong h; /* Used for numeric indexing 4字节 */ uint nKeyLength; /* The length of the key (for string keys) 4字节 */ void *pData; /* 4字节*/ void *pDataPtr; /* 4字节*/ struct bucket *pListNext; /* PHP arrays are ordered. This gives the next element in that order4字节*/ struct bucket *pListLast; /* and this gives the previous element 4字节 */ struct bucket *pNext; /* The next element in this (doubly) linked list 4字节*/ struct bucket *pLast; /* The previous element in this (doubly) linked list 4字节*/ char arKey[1]; /* Must be last element 1字节*/ } Bucket;
Bucket 구조에는 33바이트가 필요하며 키 길이가 4바이트보다 긴 부분은 Bucket 뒤에 요소 값이 추가됩니다. 또한 각 배열에는 arBuckets가 가리키는 버킷 포인터 배열이 할당됩니다. 추가된 각 요소마다 포인터가 필요하다고 말할 수는 없지만 실제 상황은 더 나쁠 수 있습니다. 이는 하나의 배열 요소가 54바이트를 차지할 것으로 계산되며 이는 위의 추정과 거의 동일합니다.
빈 배열은 최소 14(zval) + 39(HashTable) + 33(arBuckets) = 86바이트를 차지합니다. 변수로서 기호 테이블에 위치가 있어야 하며 배열 요소이기도 하므로 비어 있습니다. 설명하고 저장하려면 배열 변수 118바이트가 필요합니다. 공간적인 관점에서 볼 때 작은 배열은 평균적으로 더 비쌉니다. 물론 스크립트는 많은 수의 작은 배열로 채워지지 않으며 더 작은 공간 비용으로 프로그래밍 편의성을 얻을 수 있습니다. 그러나 배열을 컨테이너로 사용하면 이야기가 달라집니다. 실제 응용 프로그램에서는 요소가 많은 다차원 배열을 자주 접하게 됩니다. 예를 들어, 10k 요소의 1차원 배열은 약 540k의 메모리를 소비하는 반면 10k의 2차원 배열은 실제로 23M을 소비하므로 작은 배열은 실제로 그만한 가치가 없습니다.
위 내용은 PHP 배열 메모리 사용량 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!