dmitry Tue, 20 Apr 2010 10:49:22 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=298202
Log:
Added an optimization which saves memory and emalloc/efree calls for empty
HashTables
Changed paths:
U php/php-src/trunk/NEWS
U php/php-src/trunk/Zend/zend_hash.c
Modified: php/php-src/trunk/NEWS
===================================================================
--- php/php-src/trunk/NEWS 2010-04-20 10:44:19 UTC (rev 298201)
+++ php/php-src/trunk/NEWS 2010-04-20 10:49:22 UTC (rev 298202)
@@ -4,6 +4,8 @@
- Upgraded bundled sqlite to version 3.6.23.1. (Ilia)
- Upgraded bundled PCRE to version 8.02. (Ilia)
+- Added an optimization which saves memory and emalloc/efree calls for empty
+ HashTables (Stas, Dmitry)
- Added Tokyo Cabinet abstract DB support to ext/dba. (Michael Maclean)
- Added Jenkins's one-at-a-time hash support to ext/hash. (Martin Jansen)
- Added FNV-1 hash support to ext/hash. (Michael Maclean)
Modified: php/php-src/trunk/Zend/zend_hash.c
===================================================================
--- php/php-src/trunk/Zend/zend_hash.c 2010-04-20 10:44:19 UTC (rev 298201)
+++ php/php-src/trunk/Zend/zend_hash.c 2010-04-20 10:49:22 UTC (rev 298202)
@@ -132,12 +132,18 @@
(p)->pDataPtr=NULL;
\
}
+#define CHECK_INIT(ht) do {
\
+ if (UNEXPECTED((ht)->nTableMask == 0)) {
\
+ (ht)->nTableMask = (ht)->nTableSize - 1;
\
+ (ht)->arBuckets = (Bucket **) pecalloc((ht)->nTableSize,
sizeof(Bucket *), (ht)->persistent); \
+ }
\
+} while (0)
+
+static const Bucket *uninitialized_bucket = NULL;
-
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t
pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
{
uint i = 3;
- Bucket **tmp;
SET_INCONSISTENT(HT_OK);
@@ -151,9 +157,9 @@
ht->nTableSize = 1 << i;
}
- ht->nTableMask = ht->nTableSize - 1;
+ ht->nTableMask = 0; /* 0 means that ht->arBuckets is uninitialized
*/
ht->pDestructor = pDestructor;
- ht->arBuckets = NULL;
+ ht->arBuckets = (Bucket**)&uninitialized_bucket;
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
@@ -162,21 +168,6 @@
ht->persistent = persistent;
ht->nApplyCount = 0;
ht->bApplyProtection = 1;
-
- /* Uses ecalloc() so that Bucket* == NULL */
- if (persistent) {
- tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *));
- if (!tmp) {
- return FAILURE;
- }
- ht->arBuckets = tmp;
- } else {
- tmp = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *));
- if (tmp) {
- ht->arBuckets = tmp;
- }
- }
-
return SUCCESS;
}
@@ -212,6 +203,8 @@
return FAILURE;
}
+ CHECK_INIT(ht);
+
h = zend_inline_hash_func(arKey, nKeyLength);
nIndex = h & ht->nTableMask;
@@ -278,6 +271,7 @@
return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
}
+ CHECK_INIT(ht);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
@@ -350,6 +344,7 @@
Bucket *p;
IS_CONSISTENT(ht);
+ CHECK_INIT(ht);
if (flag & HASH_NEXT_INSERT) {
h = ht->nNextFreeElement;
@@ -440,6 +435,9 @@
uint nIndex;
IS_CONSISTENT(ht);
+ if (UNEXPECTED(ht->nNumOfElements == 0)) {
+ return SUCCESS;
+ }
memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
p = ht->pListHead;
@@ -530,7 +528,9 @@
}
pefree(q, ht->persistent);
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
@@ -556,7 +556,9 @@
}
pefree(q, ht->persistent);
}
- memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
+ if (ht->nTableMask) {
+ memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
+ }
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
@@ -630,7 +632,9 @@
while (p != NULL) {
p = zend_hash_apply_deleter(ht, p);
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
@@ -647,7 +651,9 @@
p = ht->pListTail;
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
@@ -1177,6 +1183,7 @@
p = pos ? (*pos) : ht->pInternalPointer;
IS_CONSISTENT(ht);
+ CHECK_INIT(ht);
if (p) {
if (key_type == HASH_KEY_IS_LONG) {
@@ -1533,6 +1540,10 @@
Bucket *p;
uint i;
+ if (UNEXPECTED(ht->nNumOfElements == 0)) {
+ zend_output_debug_string(0, "The hash is empty");
+ return;
+ }
for (i = 0; i < ht->nTableSize; i++) {
p = ht->arBuckets[i];
while (p != NULL) {
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php