Skip to content

Commit 025fcff

Browse files
committed
Optimize array_fill_keys()
Move the refcount update outside of the loop. For the following benchmark: ```php $r = range(0, 1000); $v = new stdClass(); for ($i = 0; $i < 100000; $i++) { array_fill_keys($r, $v); } ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php_old ../x.php Time (mean ± σ): 507.5 ms ± 4.8 ms [User: 505.1 ms, System: 1.2 ms] Range (min … max): 501.2 ms … 518.4 ms 10 runs Benchmark 2: ./sapi/cli/php ../x.php Time (mean ± σ): 479.8 ms ± 3.1 ms [User: 476.8 ms, System: 1.8 ms] Range (min … max): 475.0 ms … 486.7 ms 10 runs Summary ./sapi/cli/php ../x.php ran 1.06 ± 0.01 times faster than ./sapi/cli/php_old ../x.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 343.9 ms ± 3.1 ms [User: 341.1 ms, System: 2.3 ms] Range (min … max): 337.9 ms … 347.8 ms 10 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 357.8 ms ± 2.3 ms [User: 355.7 ms, System: 1.6 ms] Range (min … max): 355.0 ms … 362.6 ms 10 runs Summary ./sapi/cli/php x.php ran 1.04 ± 0.01 times faster than ./sapi/cli/php_old x.php ```
1 parent 2523491 commit 025fcff

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

Zend/zend_hash.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,17 @@ static zend_always_inline bool zend_hash_str_exists_ind(const HashTable *ht, con
473473
Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF);
474474
}
475475

476+
static zend_always_inline zval *zend_symtable_add(HashTable *ht, zend_string *key, zval *pData)
477+
{
478+
zend_ulong idx;
479+
480+
if (ZEND_HANDLE_NUMERIC(key, idx)) {
481+
return zend_hash_index_add(ht, idx, pData);
482+
} else {
483+
return zend_hash_add(ht, key, pData);
484+
}
485+
}
486+
476487
static zend_always_inline zval *zend_symtable_add_new(HashTable *ht, zend_string *key, zval *pData)
477488
{
478489
zend_ulong idx;

ext/standard/array.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2826,20 +2826,28 @@ PHP_FUNCTION(array_fill_keys)
28262826
ZEND_PARSE_PARAMETERS_END();
28272827

28282828
/* Initialize return array */
2829-
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
2829+
uint32_t keys_count = zend_hash_num_elements(Z_ARRVAL_P(keys));
2830+
array_init_size(return_value, keys_count);
2831+
2832+
if (Z_REFCOUNTED_P(val)) {
2833+
GC_ADDREF_EX(Z_COUNTED_P(val), keys_count);
2834+
}
28302835

28312836
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) {
28322837
ZVAL_DEREF(entry);
2833-
Z_TRY_ADDREF_P(val);
28342838
if (Z_TYPE_P(entry) == IS_LONG) {
2835-
zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val);
2839+
zend_hash_index_add(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val);
28362840
} else {
28372841
zend_string *tmp_key;
28382842
zend_string *key = zval_get_tmp_string(entry, &tmp_key);
2839-
zend_symtable_update(Z_ARRVAL_P(return_value), key, val);
2843+
zend_symtable_add(Z_ARRVAL_P(return_value), key, val);
28402844
zend_tmp_string_release(tmp_key);
28412845
}
28422846
} ZEND_HASH_FOREACH_END();
2847+
2848+
if (Z_REFCOUNTED_P(val)) {
2849+
GC_DELREF_EX(Z_COUNTED_P(val), keys_count - zend_hash_num_elements(Z_ARRVAL_P(return_value)));
2850+
}
28432851
}
28442852
/* }}} */
28452853

0 commit comments

Comments
 (0)