PHP配列とspl固定配列

WBOY
リリース: 2016-06-13 13:03:30
オリジナル
997 人が閲覧しました

PHP 配列と spl 固定配列
php 固定配列は、PHP 標準ライブラリ (spl) に属するデータ構造です。通常の PHP 配列と比較して、固定配列は添字を定義するために整数のみを使用でき、その名前が示すように固定長であるため、通常の配列よりもメモリの使用量が少なく、高速であることが利点です。以下で分析します。まず簡単なテストを実行し、10W の a を配列に入れます。

define("MAX", 100000);

//simple array
function simple_arr()
{
        $i = MAX;
	$arr = array();
	while ($i--)
		$arr[$i]= 'a';
}

// fix array
function fix_arr()
{	
	$i = MAX;
	$arr = new SplFixedArray(MAX);
	while ($i--)
		$arr[$i]= 'a';		
}

//fix array with set
function fix_set_arr()
{
	$i = MAX;
	$arr = new SplFixedArray(MAX);
	while ($i--)
		$arr->offsetSet($i, "a");
}
ログイン後にコピー

消費時間

一般的な配列: 0.084696054458618

固定配列: 0.048405885696411

固定配列は offsetSet メソッドを呼び出すことでコピーされます: 0.27650499343872

メモリ消費量

一般配列: 9324672

固定配列: 4800464

配列が offsetSet メソッドを呼び出してコピーする問題を修正しました: 4800344


スペース消費量の比較

空間と時間の効率の観点から見ると、固定配列の消費量は通常の配列よりも大幅に少なくなります。拡張機能の組み込み関数 offsetSet を使用して固定配列を割り当てるのは、添え字を使用して割り当てるよりもはるかに遅くなります。これは、拡張機能の組み込みメソッドを使用して配列値を割り当てるには、PHP 内の関数テーブルのクエリが 1 つ必要になるためです。 。

一般的な配列の場合、PHP は内部的にハッシュテーブルを介して配列の値に対応し、これは PHP ソース コード Zend/zend_hash で定義されます。 h ハッシュ関連の構造定義と関数。

typedef struct bucket {
	ulong h;						/* Used for numeric indexing */
	uint nKeyLength;
	void *pData;
	void *pDataPtr;
	struct bucket *pListNext;
	struct bucket *pListLast;
	struct bucket *pNext;
	struct bucket *pLast;
	const char *arKey;
} Bucket;

typedef struct _hashtable {
	uint nTableSize;
	uint nTableMask;
	uint nNumOfElements;
	ulong nNextFreeElement;
	Bucket *pInternalPointer;	/* Used for element traversal */
	Bucket *pListHead;
	Bucket *pListTail;
	Bucket **arBuckets;
	dtor_func_t pDestructor;
	zend_bool persistent;
	unsigned char nApplyCount;
	zend_bool bApplyProtection;
#if ZEND_DEBUG
	int inconsistent;
#endif
} HashTable
	
ログイン後にコピー

上記のコードに示すように、10 要素の PHP 配列が占めるスペースは、sizeof(HashTable) + 10 * size(Bucket) + 要素自体が占めるスペースです。これはコードです。実際には、PHP 内部ではもう少し複雑です。HashTable の nTableSize は常に 2^n であるため、要素が 10 個ある場合でも、PHP は単純なアルゴリズムを通じて 2^4、つまり 16 スロットを占有することができます。したがって、実際に占有されるスペースは sizeof (HashTable) + 16 * sizeof(Bucket) + となります。 要素自体がスペースを占有します。 (スペースの計算では、添字が整数の場合のみが考慮されます)

次のコードに示すように、対応する固定配列は、ユーザーによって渡されたサイズによって直接初期化されます。同じ 10 要素の配列は、要素自体が占有する 10* スペースのみを必要とします。

static void spl_fixedarray_init(spl_fixedarray *array, long size TSRMLS_DC) /* {{{ */
{
	if (size > 0) {
		array->size = 0; /* reset size in case ecalloc() fails */
		array->elements = ecalloc(size, sizeof(zval *));
		array->size = size;
	} else {
		array->elements = NULL;
		array->size = 0;
	}
}
ログイン後にコピー

時間比較

固定配列の場合、メモリの適用は 1 ステップで実行され、メモリが不足している場合はエラーが報告されます。

通常の配列の場合、配列空間が動的に割り当てられるため、要素数が事前に分からないため、PHPが空の配列を初期化する際、デフォルトでは8スロットになりますが、スロットが足りない場合は*2となります。 hashTbale の要素数が nTableSize より大きい場合、hashTable のサイズが変更され、再ハッシュされるため、かなりの時間がかかります。

static int zend_hash_do_resize(HashTable *ht)
{
	Bucket **t;
#ifdef ZEND_SIGNALS
	TSRMLS_FETCH();
#endif

	IS_CONSISTENT(ht);

	if ((ht->nTableSize << 1) > 0) {	/* Let's double the table size */
		t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
		if (t) {
			HANDLE_BLOCK_INTERRUPTIONS();
			ht->arBuckets = t;
			ht->nTableSize = (ht->nTableSize << 1);
			ht->nTableMask = ht->nTableSize - 1;
			zend_hash_rehash(ht);
			HANDLE_UNBLOCK_INTERRUPTIONS();
			return SUCCESS;
		}
		return FAILURE;
	}
	return SUCCESS;
}

ZEND_API int zend_hash_rehash(HashTable *ht)
{
	Bucket *p;
	uint nIndex;

	IS_CONSISTENT(ht);
	if (UNEXPECTED(ht->nNumOfElements == 0)) {
		return SUCCESS;
	}

	memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
	p = ht->pListHead;
	while (p != NULL) {
		nIndex = p->h & ht->nTableMask;
		CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
		ht->arBuckets[nIndex] = p;
		p = p->pListNext;
	}
	return SUCCESS;
}
ログイン後にコピー


比較すると、固定配列と比較して、PHP の通常の配列のメモリと時間の消費量のほとんどがシンボル テーブルで使用されていることがわかります。 PHP の内部実装における重要な考え方は、hashTable を使用してデータ要素を迅速に見つけることです。また、PHP の配列スペースは動的に割り当てられるため、内部実装では C 言語が使用されます。配列のスペース割り当てには固定割り当てしかありません。PHP 配列が動的にスペースを割り当てているとユーザーに感じさせるには、サイズ変更と再ハッシュによってのみ実現できます。そのため、固定配列と比較して、同じ数の要素を割り当てる時間は遅くなります。 。つまり、通常のアレイと固定アレイにはそれぞれ利点と欠点があり、特定のビジネス シナリオを考慮する必要があるため、固定アレイの方が時間とスペースの消費が少ないとは言えません。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート