]> granicus.if.org Git - php/commitdiff
Optimize array_unique()
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 1 Aug 2017 16:07:26 +0000 (18:07 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 1 Aug 2017 16:08:38 +0000 (18:08 +0200)
In SORT_STRING mode, instead of sorting the array, build a hash of
seen elements.

ext/standard/array.c
ext/standard/tests/array/array_unique_variation8.phpt

index d6ea5c481b42870fc33f3d9d8682320fa193a480..9ddbf1f3bf22abbc14d66b6e9047465e776bf921 100644 (file)
@@ -4477,14 +4477,51 @@ PHP_FUNCTION(array_unique)
                Z_PARAM_LONG(sort_type)
        ZEND_PARSE_PARAMETERS_END();
 
-       cmp = php_get_data_compare_func(sort_type, 0);
-
-
        if (Z_ARRVAL_P(array)->nNumOfElements <= 1) {   /* nothing to do */
                ZVAL_COPY(return_value, array);
                return;
        }
 
+       if (sort_type == PHP_SORT_STRING) {
+               HashTable seen;
+               zend_long num_key;
+               zend_string *str_key;
+               zval *val;
+
+               zend_hash_init(&seen, zend_hash_num_elements(Z_ARRVAL_P(array)), NULL, NULL, 0);
+               array_init(return_value);
+
+               ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_key, str_key, val) {
+                       zval *retval;
+                       if (Z_TYPE_P(val) == IS_STRING) {
+                               retval = zend_hash_add_empty_element(&seen, Z_STR_P(val));
+                       } else {
+                               zend_string *str_val = zval_get_string(val);
+                               retval = zend_hash_add_empty_element(&seen, str_val);
+                               zend_string_release(str_val);
+                       }
+
+                       if (retval) {
+                               /* First occurrence of the value */
+                               if (UNEXPECTED(Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1)) {
+                                       ZVAL_DEREF(val);
+                               }
+                               Z_TRY_ADDREF_P(val);
+
+                               if (str_key) {
+                                       zend_hash_add_new(Z_ARRVAL_P(return_value), str_key, val);
+                               } else {
+                                       zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, val);
+                               }
+                       }
+               } ZEND_HASH_FOREACH_END();
+
+               zend_hash_destroy(&seen);
+               return;
+       }
+
+       cmp = php_get_data_compare_func(sort_type, 0);
+
        RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array)));
 
        /* create and sort array with pointers to the target_hash buckets */
index 3b4eac9f7594b6ae0c09b8431584889c17ccc751..8b67adfbab097f1072f6baad21c159a9399a8329 100644 (file)
@@ -35,22 +35,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
-
-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]=>