10% speedup patch in zend_hash_copy
| From: | Thies C. Arntzen | Date: | Sun, 25 Nov 2001 16:29:25 +0000 |
| Subject: | 10% speedup patch in zend_hash_copy | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-71600@lists.php.net to get a copy of this message | ||
hi -
this litte patch makes zend_hash_copy around 10% faster by
taking a "shortcut"
zeev, andi -
is this "commitable" or do you have any objections?
tc
Index: zend_hash.c =================================================================== RCS file: /repository/Zend/zend_hash.c,v retrieving revision 1.81 diff -u -r1.81 zend_hash.c --- zend_hash.c 2001/10/04 12:47:59 1.81 +++ zend_hash.c 2001/11/25 16:22:22 @@ -754,23 +754,77 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size) { Bucket *p; + Bucket *np; void *new_entry; + uint nIndex; IS_CONSISTENT(source); IS_CONSISTENT(target); - p = source->pListHead; - while (p) { - if (p->nKeyLength) { - zend_hash_update(target, p->arKey, p->nKeyLength, p->pData, size, &new_entry); - } else { - zend_hash_index_update(target, p->h, p->pData, size, &new_entry); + if (target->nNumOfElements == 0) { + target->nTableSize = source->nTableSize; + target->nTableMask = source->nTableMask; + target->nNumOfElements = source->nNumOfElements; + target->nNextFreeElement = source->nNextFreeElement; + + pefree(target->arBuckets, target->persistent); + target->arBuckets = (Bucket **) pecalloc(target->nTableSize, sizeof(Bucket *), target->persistent); + + p = source->pListHead; + while (p) { + if (p->nKeyLength) { + np = (Bucket *) pemalloc(sizeof(Bucket)-1+p->nKeyLength, target->persistent); + memcpy(np->arKey, p->arKey, p->nKeyLength); + np->nKeyLength = p->nKeyLength; + } else { + np = (Bucket *) pemalloc(sizeof(Bucket)-1+p->nKeyLength, target->persistent); + np->nKeyLength = 0; + } + + np->h = p->h; + + if (size == sizeof(void*)) { + memcpy(&(np)->pDataPtr, p->pData, sizeof(void *)); + np->pData = &np->pDataPtr; + } else { + np->pData = (void *) pemalloc(size, target->persistent); + /* XXX exit? + if (!(p)->pData) { + pefree(p, (ht)->persistent); + return FAILURE; + } + */ + memcpy(np->pData, p->pData, size); + np->pDataPtr=NULL; + } + + nIndex = p->h & target->nTableMask; + CONNECT_TO_BUCKET_DLLIST(np, target->arBuckets[nIndex]); + target->arBuckets[nIndex] = np; + + CONNECT_TO_GLOBAL_DLLIST(np, target); + + if (pCopyConstructor) { + pCopyConstructor(np->pData); + } + + p = p->pListNext; } - if (pCopyConstructor) { - pCopyConstructor(new_entry); - } - p = p->pListNext; + } else { + p = source->pListHead; + while (p) { + if (p->nKeyLength) { + zend_hash_update(target, p->arKey, p->nKeyLength, p->pData, size, &new_entry); + } else { + zend_hash_index_update(target, p->h, p->pData, size, &new_entry); + } + if (pCopyConstructor) { + pCopyConstructor(new_entry); + } + p = p->pListNext; + } } + target->pInternalPointer = target->pListHead; }
Index: zend_hash.c =================================================================== RCS file: /repository/Zend/zend_hash.c,v retrieving revision 1.81 diff -u -r1.81 zend_hash.c --- zend_hash.c 2001/10/04 12:47:59 1.81 +++ zend_hash.c 2001/11/25 16:22:22 @@ -754,23 +754,77 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size) { Bucket *p; + Bucket *np; void *new_entry; + uint nIndex; IS_CONSISTENT(source); IS_CONSISTENT(target); - p = source->pListHead; - while (p) { - if (p->nKeyLength) { - zend_hash_update(target, p->arKey, p->nKeyLength, p->pData, size, &new_entry); - } else { - zend_hash_index_update(target, p->h, p->pData, size, &new_entry); + if (target->nNumOfElements == 0) { + target->nTableSize = source->nTableSize; + target->nTableMask = source->nTableMask; + target->nNumOfElements = source->nNumOfElements; + target->nNextFreeElement = source->nNextFreeElement; + + pefree(target->arBuckets, target->persistent); + target->arBuckets = (Bucket **) pecalloc(target->nTableSize, sizeof(Bucket *), target->persistent); + + p = source->pListHead; + while (p) { + if (p->nKeyLength) { + np = (Bucket *) pemalloc(sizeof(Bucket)-1+p->nKeyLength, target->persistent); + memcpy(np->arKey, p->arKey, p->nKeyLength); + np->nKeyLength = p->nKeyLength; + } else { + np = (Bucket *) pemalloc(sizeof(Bucket)-1+p->nKeyLength, target->persistent); + np->nKeyLength = 0; + } + + np->h = p->h; + + if (size == sizeof(void*)) { + memcpy(&(np)->pDataPtr, p->pData, sizeof(void *)); + np->pData = &np->pDataPtr; + } else { + np->pData = (void *) pemalloc(size, target->persistent); + /* XXX exit? + if (!(p)->pData) { + pefree(p, (ht)->persistent); + return FAILURE; + } + */ + memcpy(np->pData, p->pData, size); + np->pDataPtr=NULL; + } + + nIndex = p->h & target->nTableMask; + CONNECT_TO_BUCKET_DLLIST(np, target->arBuckets[nIndex]); + target->arBuckets[nIndex] = np; + + CONNECT_TO_GLOBAL_DLLIST(np, target); + + if (pCopyConstructor) { + pCopyConstructor(np->pData); + } + + p = p->pListNext; } - if (pCopyConstructor) { - pCopyConstructor(new_entry); - } - p = p->pListNext; + } else { + p = source->pListHead; + while (p) { + if (p->nKeyLength) { + zend_hash_update(target, p->arKey, p->nKeyLength, p->pData, size, &new_entry); + } else { + zend_hash_index_update(target, p->h, p->pData, size, &new_entry); + } + if (pCopyConstructor) { + pCopyConstructor(new_entry); + } + p = p->pListNext; + } } + target->pInternalPointer = target->pListHead; }