PHP は本当に多くのメモリを消費しますか?そこで私はこの機会を利用して、PHP のデータ型の実装について学びました。この記事では主に、PHP 配列の低メモリ使用率と弱い型の詳細な解釈を紹介します。一定の参考値があるので、興味のある方は参考にしてください。
まずテストをしてみましょう:
<?php echo memory_get_usage() , '<br>'; $start = memory_get_usage(); $a = Array(); for ($i=0; $i<1000; $i++) { $a[$i] = $i + $i; } $end = memory_get_usage(); echo memory_get_usage() , '<br>'; echo 'argv:', ($end - $start)/1000 ,'bytes' , '<br>';
結果:
353352
437848
argv: 84.416bytes
1000 要素の整数配列はメモリを消費します (4 37848 - 353352) バイト、約 82KB 、つまり各要素は 84 バイトのメモリを占有します。 C 言語では、int は 4 バイトを占有し、全体で 20 倍の違いがあります。
しかし、インターネットでは、memory_get_usage() によって返される結果はすべての配列占有ではなく、PHP 自体の構造も含まれていると言われています。そのため、別の方法を試し、PHP 組み込み関数を使用して配列を生成してください。
<?php $start = memory_get_usage(); $a = array_fill(0, 10000, 1); $end = memory_get_usage(); //10k elements array; echo 'argv:', ($end - $start )/10000,'byte' , '<br>';出力は次のとおりです: argv:54.5792byte
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 は、zvalue_value 型の value 変数を使用して変数の値を格納します。 zval は共用体であり、次のように定義されます:
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;共用体型によって占有されるメモリのサイズは、その最大のメンバーによって占有されるデータ領域によって決まります。 zvalue_value では、str 構造体の int が 4 バイト、char ポインタが 4 バイトを占めるため、zvalue_value 全体が占めるメモリは 8 バイトになります。
typedef struct _hashtable { uint nTableSize; //表长度,并非元素个数 uint nTableMask;//表的掩码,始终等于nTableSize-1 uint nNumOfElements;//存储的元素个数 ulong nNextFreeElement;//指向下一个空的元素位置 Bucket *pInternalPointer;//foreach循环时,用来记录当前遍历到的元素位置 Bucket *pListHead; Bucket *pListTail; Bucket **arBuckets;//存储的元素数组 dtor_func_t pDestructor;//析构函数 zend_bool persistent;//是否持久保存。从这可以发现,PHP数组是可以实现持久保存在内存中的,而无需每次请求都重新加载。 unsigned char nApplyCount; zend_bool bApplyProtection; } HashTable;テーブルのサイズとそれに含まれる要素の数を記録するいくつかの属性変数に加えて、Bucket の定義方法:
typedef struct bucket { ulong h; //数组索引 uint nKeyLength; //字符串索引的长度 void *pData; //实际数据的存储地址 void *pDataPtr; //引入的数据存储地址 struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; //双向链表的下一个元素的地址 struct bucket *pLast;//双向链表的下一个元素地址 char arKey[1]; /* Must be last element */ } Bucket;リンク リストと少し似ています。Bucket は特定のデータとポインターを含むリンク リスト ノードのようなもので、HashTable は Bucket 要素の文字列を格納する配列です。 PHP での多次元配列の実装は、バケットに格納される別の HashTable にすぎません。
PHP 配列がメモリを過剰に消費する問題の解決策_PHP チュートリアル
PHP 配列が過剰に消費する問題の解決策メモリが多い Method_php のヒント
以上がPHP 配列の低メモリ使用率の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。