summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2015-01-15 13:57:06 +0800
committerXinchen Hui <laruence@php.net>2015-01-15 13:57:06 +0800
commitb57dc41e075a88e8808d66973521dfdbd4a43336 (patch)
treefbfb91af5f780980c429a682b5a563adbc5e938f
parent8a0bc38535f34d2e1063e9f3e3bf356300d07331 (diff)
downloadphp-git-b57dc41e075a88e8808d66973521dfdbd4a43336.tar.gz
Optimize array_unique to save some comparation calls
-rw-r--r--ext/standard/array.c90
-rw-r--r--ext/standard/tests/array/array_unique_variation8.phpt12
2 files changed, 73 insertions, 29 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 6e8b8e5624..471ba56aa2 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -396,6 +396,57 @@ static int php_array_data_compare(const void *a, const void *b) /* {{{ */
}
/* }}} */
+static int php_array_data_compare_unique(const void *a, const void *b) /* {{{ */
+{
+ Bucket *f;
+ Bucket *s;
+ zval result;
+ zval *first;
+ zval *second;
+ int ret;
+
+ f = (Bucket *) a;
+ s = (Bucket *) b;
+
+ first = &f->val;
+ second = &s->val;
+
+ if (Z_TYPE_P(first) == IS_INDIRECT) {
+ first = Z_INDIRECT_P(first);
+ } else if (Z_TYPE_P(first) == IS_UNDEF) {
+ if (Z_TYPE_P(second) != IS_UNDEF) {
+ return -1;
+ }
+ return 0;
+ }
+
+ if (Z_TYPE_P(second) == IS_INDIRECT) {
+ second = Z_INDIRECT_P(second);
+ } else if (Z_TYPE_P(second) == IS_UNDEF) {
+ return 1;
+ }
+
+ if (ARRAYG(compare_func)(&result, first, second) == FAILURE) {
+ return 0;
+ }
+
+ if (EXPECTED(Z_TYPE(result) == IS_LONG)) {
+ ret = ZEND_NORMALIZE_BOOL(Z_LVAL(result));
+ } else if (Z_TYPE(result) == IS_DOUBLE) {
+ ret = ZEND_NORMALIZE_BOOL(Z_DVAL(result));
+ } else {
+ ret = ZEND_NORMALIZE_BOOL(zval_get_long(&result));
+ }
+
+ if (ret == 0) {
+ ZVAL_UNDEF(&s->val);
+ ret = 1;
+ }
+
+ return ret;
+}
+/* }}} */
+
static int php_array_reverse_data_compare(const void *a, const void *b) /* {{{ */
{
return php_array_data_compare(a, b) * -1;
@@ -3158,7 +3209,7 @@ PHP_FUNCTION(array_unique)
}
/* create and sort array with pointers to the target_hash buckets */
- arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->u.flags & HASH_FLAG_PERSISTENT);
+ arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->u.flags & HASH_FLAG_PERSISTENT);
if (!arTmp) {
zval_dtor(return_value);
RETURN_FALSE;
@@ -3171,30 +3222,35 @@ PHP_FUNCTION(array_unique)
arTmp[i].i = i;
i++;
}
- ZVAL_UNDEF(&arTmp[i].b.val);
zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
- php_array_data_compare, (swap_func_t)array_bucketindex_swap);
+ php_array_data_compare_unique, (swap_func_t)array_bucketindex_swap);
/* go through the sorted array and delete duplicates from the copy */
- lastkept = arTmp;
- for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
- if (php_array_data_compare(lastkept, cmpdata)) {
- lastkept = cmpdata;
- } else {
- if (lastkept->i > cmpdata->i) {
- p = &lastkept->b;
+ lastkept = NULL;
+ for (idx = 0; idx < i; idx++) {
+ cmpdata = &arTmp[idx];
+ if (Z_TYPE(cmpdata->b.val) != IS_UNDEF) {
+ if (lastkept == NULL) {
lastkept = cmpdata;
- } else {
- p = &cmpdata->b;
+ continue;
}
- if (p->key == NULL) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
+ if (php_array_data_compare(lastkept, cmpdata)) {
+ lastkept = cmpdata;
+ continue;
} else {
- if (Z_ARRVAL_P(return_value) == &EG(symbol_table).ht) {
- zend_delete_global_variable(p->key);
+ if (lastkept->i > cmpdata->i) {
+ p = &lastkept->b;
+ lastkept = cmpdata;
} else {
- zend_hash_del(Z_ARRVAL_P(return_value), p->key);
+ p = &cmpdata->b;
}
}
+ } else {
+ p = &cmpdata->b;
+ }
+ if (p->key == NULL) {
+ zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
+ } else {
+ zend_hash_del(Z_ARRVAL_P(return_value), p->key);
}
}
pefree(arTmp, Z_ARRVAL_P(array)->u.flags & HASH_FLAG_PERSISTENT);
diff --git a/ext/standard/tests/array/array_unique_variation8.phpt b/ext/standard/tests/array/array_unique_variation8.phpt
index 3b4eac9f75..5a82c87902 100644
--- a/ext/standard/tests/array/array_unique_variation8.phpt
+++ b/ext/standard/tests/array/array_unique_variation8.phpt
@@ -40,18 +40,6 @@ Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
-
-Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
-
-Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
-
-Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
-
-Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
-
-Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
-
-Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
array(1) {
[0]=>
array(4) {