lbarnaud Wed Nov 19 14:41:41 2008 UTC Modified files: (Branch: PHP_5_3) /php-src/ext/spl spl_array.c /php-src NEWS Log: Improved ArrayObject performance (made spl_hash_verify_pos() an O(1) and removed some spl_array_get_hash_table() calls). Fixes #46039
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_array.c?r1=1.71.2.17.2.13.2.33&r2=1.71.2.17.2.13.2.34&diff_format=u Index: php-src/ext/spl/spl_array.c diff -u php-src/ext/spl/spl_array.c:1.71.2.17.2.13.2.33 php-src/ext/spl/spl_array.c:1.71.2.17.2.13.2.34 --- php-src/ext/spl/spl_array.c:1.71.2.17.2.13.2.33 Wed Nov 19 02:00:53 2008 +++ php-src/ext/spl/spl_array.c Wed Nov 19 14:41:40 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_array.c,v 1.71.2.17.2.13.2.33 2008/11/19 02:00:53 colder Exp $ */ +/* $Id: spl_array.c,v 1.71.2.17.2.13.2.34 2008/11/19 14:41:40 lbarnaud Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -63,6 +63,7 @@ zval *array; zval *retval; HashPosition pos; + ulong pos_h; int ar_flags; int is_self; zend_function *fptr_offset_get; @@ -92,24 +93,44 @@ static void spl_array_rewind(spl_array_object *intern TSRMLS_DC); -SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */ +static void spl_array_update_pos(spl_array_object* intern) /* {{{ */ +{ + Bucket *pos; + if ((pos = intern->pos)) { + intern->pos_h = pos->h; + } +} /* }}} */ + +static void spl_array_set_pos(spl_array_object* intern, HashPosition pos) /* {{{ */ +{ + intern->pos = pos; + spl_array_update_pos(intern); +} /* }}} */ + +SPL_API int spl_hash_verify_pos_ex(spl_array_object * intern, HashTable * ht TSRMLS_DC) /* {{{ */ { - HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); Bucket *p; /* IS_CONSISTENT(ht);*/ /* HASH_PROTECT_RECURSION(ht);*/ - p = ht->pListHead; + p = ht->arBuckets[intern->pos_h & ht->nTableMask]; while (p != NULL) { if (p == intern->pos) { return SUCCESS; } - p = p->pListNext; + p = p->pNext; } /* HASH_UNPROTECT_RECURSION(ht); */ spl_array_rewind(intern TSRMLS_CC); return FAILURE; + +} /* }}} */ + +SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */ +{ + HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + return spl_hash_verify_pos_ex(intern, ht TSRMLS_CC); } /* }}} */ @@ -609,7 +630,7 @@ spl_array_write_dimension(object, NULL, append_value TSRMLS_CC); if (!intern->pos) { - intern->pos = aht->pListTail; + spl_array_set_pos(intern, aht->pListTail); } } /* }}} */ @@ -749,12 +770,11 @@ std_object_handlers.unset_property(object, member TSRMLS_CC); } /* }}} */ -static int spl_array_skip_protected(spl_array_object *intern TSRMLS_DC) /* {{{ */ +static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ { char *string_key; uint string_length; ulong num_key; - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); if (Z_TYPE_P(intern->array) == IS_OBJECT) { do { @@ -769,27 +789,39 @@ return FAILURE; } zend_hash_move_forward_ex(aht, &intern->pos); + spl_array_update_pos(intern); } while (1); } return FAILURE; -} -/* }}} */ +} /* }}} */ -static int spl_array_next(spl_array_object *intern TSRMLS_DC) /* {{{ */ +static int spl_array_next_no_verify(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ { - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + zend_hash_move_forward_ex(aht, &intern->pos); + spl_array_update_pos(intern); + if (Z_TYPE_P(intern->array) == IS_OBJECT) { + return spl_array_skip_protected(intern, aht TSRMLS_CC); + } else { + return zend_hash_has_more_elements_ex(aht, &intern->pos); + } +} /* }}} */ - if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { +static int spl_array_next_ex(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ +{ + if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); return FAILURE; - } else { - zend_hash_move_forward_ex(aht, &intern->pos); - if (Z_TYPE_P(intern->array) == IS_OBJECT) { - return spl_array_skip_protected(intern TSRMLS_CC); - } else { - return zend_hash_has_more_elements_ex(aht, &intern->pos); - } } + + return spl_array_next_no_verify(intern, aht TSRMLS_CC); +} /* }}} */ + +static int spl_array_next(spl_array_object *intern TSRMLS_DC) /* {{{ */ +{ + HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + + return spl_array_next_ex(intern, aht TSRMLS_CC); + } /* }}} */ /* define an overloaded iterator structure */ @@ -823,7 +855,7 @@ return FAILURE; } - if (object->pos && (object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) { + if (object->pos && (object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and internal position is no longer valid"); return FAILURE; } else { @@ -863,7 +895,7 @@ return HASH_KEY_NON_EXISTANT; } - if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) { + if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and internal position is no longer valid"); return HASH_KEY_NON_EXISTANT; } @@ -888,15 +920,24 @@ return; } - if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) { + if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::next(): Array was modified outside object and internal position is no longer valid"); } else { - spl_array_next(object TSRMLS_CC); + spl_array_next_no_verify(object, aht TSRMLS_CC); } } } /* }}} */ +static void spl_array_rewind_ex(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ +{ + + zend_hash_internal_pointer_reset_ex(aht, &intern->pos); + spl_array_update_pos(intern); + spl_array_skip_protected(intern, aht TSRMLS_CC); + +} /* }}} */ + static void spl_array_rewind(spl_array_object *intern TSRMLS_DC) /* {{{ */ { HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); @@ -906,8 +947,7 @@ return; } - zend_hash_internal_pointer_reset_ex(aht, &intern->pos); - spl_array_skip_protected(intern TSRMLS_CC); + spl_array_rewind_ex(intern, aht TSRMLS_CC); } /* }}} */ @@ -1197,7 +1237,7 @@ while(intern->pos && spl_array_next(intern TSRMLS_CC) == SUCCESS) { (*count)++; } - intern->pos = pos; + spl_array_set_pos(intern, pos); return SUCCESS; } else { *count = zend_hash_num_elements(aht); @@ -1318,7 +1358,7 @@ return; } - if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { + if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); return; } @@ -1350,7 +1390,7 @@ return; } - if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { + if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); return; } @@ -1381,7 +1421,7 @@ return; } - spl_array_next(intern TSRMLS_CC); + spl_array_next_ex(intern, aht TSRMLS_CC); } /* }}} */ @@ -1398,7 +1438,7 @@ return; } - if (intern->pos && (intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { + if (intern->pos && (intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); RETURN_FALSE; } else { @@ -1420,7 +1460,7 @@ RETURN_FALSE; } - if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { + if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); RETURN_FALSE; } @@ -1446,7 +1486,7 @@ return; } - if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { + if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); return; } http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.383&r2=1.2027.2.547.2.965.2.384&diff_format=u Index: php-src/NEWS diff -u php-src/NEWS:1.2027.2.547.2.965.2.383 php-src/NEWS:1.2027.2.547.2.965.2.384 --- php-src/NEWS:1.2027.2.547.2.965.2.383 Wed Nov 19 02:03:26 2008 +++ php-src/NEWS Wed Nov 19 14:41:40 2008 @@ -71,6 +71,7 @@ - Fixed bug #46060 (Phar::addEmptyDir() breaks) (Greg) - Fixed bug #46042 (memory leaks with reflection of mb_convert_encoding()). (Ilia) +- Fixed bug #46039 (ArrayObject iteration is slow). (Arnaud) - Fixed bug #45976 (Moved SXE from SPL to SimpleXML). (Etienne) - Fixed bug #45928 (large scripts from stdin are stripped at 16K border). (Christian Schneider, Arnaud)
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php