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