ホームページ  >  記事  >  バックエンド開発  >  PHP 配列効率_PHP チュートリアルについて引き続き説明します。

PHP 配列効率_PHP チュートリアルについて引き続き説明します。

WBOY
WBOYオリジナル
2016-07-13 17:38:31908ブラウズ

PHP は、特に大量のメモリを消費するため、配列処理が非常に非効率になることがあります。これにより、httpd プロセスが大量のリソースを消費することがよくあります。かつて bkJia Web サイトが一部のコンテンツを呼び出したところ、配列が大きすぎてメモリがオーバーフローし、Apache が頻繁にクラッシュしました。一般に、PHP で多数の配列操作を実行する場合、プログラミング設計の問題がある程度反映される可能性がありますが、配列が占有するメモリを大まかに見積もる必要があります。

まず、1000 要素の整数配列が占めるメモリを感じてください:

echomemory_get_usage() . ”;

$a = 配列();
for ($i=0; $i $a[$i] = $i + $i;
}

echomemory_get_usage() . ”;

for ($i=1000; $i $a[$i] = $i + $i;
}

echomemory_get_usage() . ”;

出力は次のとおりです:

58176
162956
267088
1000 要素の整数配列には 100k のメモリが必要で、各要素は平均 100 バイトを占有することが大まかにわかります。純粋な C では全体的に 4k しか必要としません。 Memory_get_usage() によって返される結果は、すべてが配列によって占有されているわけではなく、PHP 自体によって割り当てられたいくつかの構造も含まれています。組み込み関数によって生成された配列は、実際の空間に近い可能性があります。

echo "init mem: " .memory_get_usage() " ”;

$a = array_fill(0, 10000, 1);
echo "10k 要素: " .memory_get_usage() "、システム: " .memory_get_usage(true) " ”;
$b = array_fill(0, 10000, 1);
echo "10k 要素: " .memory_get_usage() "、システム: " .memory_get_usage(true) " ”;
入手:

初期メモリ: 58468

10k エレメント: 724696、システム: 786432
10,000 要素: 1390464、システム: 1572864
この結果から、配列の 1 つの要素は 60 バイト程度しか占有しないことがわかります。 PHP の配列変数にはまず zval 構造体が必要です。
配列の C 構造体を見てみましょう。

struct _zval_struct {

zvalue_value 値;
zend_uint refcount__gc;
zend_uchar 型;
zend_uchar is_ref__gc;
};
zvalue_value は共用体です:

typedef Union _zvalue_value {

長い lval;
ダブル dval;
構造体{
char *val;
int len;
} str;
ハッシュテーブル *ht;
zend_object_value obj;
zvalue_value;
通常、zval 構造には 8+6=14 バイトが必要です。PHP の各変数には対応する zval が必要ですが、配列、文​​字列、オブジェクトには追加のストレージ構造も必要であり、配列は HashTable です:

typedef struct _hashtable {

uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
バケット *pInternalPointer;
バケット *pListHead;
バケット *pListTail;
バケット **arBuckets;
dtor_func_t pDestructor;
zend_bool 永続的;
unsigned char nApplyCount;
zend_bool bApplyProtection;
}ハッシュテーブル;
HashTable 構造には 40 バイトが必要で、各配列要素は Bucket 構造に保存されます:

typedef 構造体バケット {

うろんh;
uint nKeyLength;
void *pData;
void *pDataPtr;
構造体バケット *pListNext;
構造体バケット *pListLast;
構造体バケット *pNext;
構造体バケット *pLast;
char arKey[1];
バケット;
Bucket 構造体には 36 バイトが必要で、キー長が 4 バイトを超える部分は Bucket の末尾に追加され、要素の値は zval 構造体になる可能性が高く、さらに各配列には Bucket ポインターが割り当てられます。 arBuckets が指す配列。ただし、追加要素ごとにポインタが必要であるとは言えませんが、状況はさらに悪化する可能性があります。これは、1 つの配列要素が 54 バイトを占有することを計算します。これは、上記の推定値からそれほど遠くありません。

空の配列は、変数として少なくとも 14(zval) + 40(HashTable) + 32(arBuckets) = 86 バイトを占め、シンボル テーブル内に位置が必要であり、配列要素でもあるため、空の配列となります。変数の記述と格納には 118 バイトが必要です。スペースの観点から見ると、小さな配列の方が平均してコストが高くなります。もちろん、スクリプトが多数の小さな配列で埋め尽くされることはなく、より少ないスペースコストでプログラミングの利便性が得られます。
しかし、配列をコンテナとして使用する場合は別の話になります。実際のアプリケーションでは、多くの要素を含む多次元配列が頻繁に発生します。たとえば、10k 要素の 1 次元配列は約 540k のメモリを消費しますが、10k の 2 次元配列は実際には 23M を消費し、小さな配列には実際には価値がありません。

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/486484.html技術記事 PHP は、配列処理において非常に非効率になる場合があり、特にメモリを大量に消費する場合には、httpd プロセスが大量のリソースを消費することがよくあります。 PHP100 Web サイトで一部のコンテンツを呼び出したところ、配列が大きすぎました...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。