Commit 7b6b233ce8e for php.net
commit 7b6b233ce8ea0c19bdac305781cb35fad1a31aff
Author: Niels Dossche <7771979+ndossche@users.noreply.github.com>
Date: Mon Nov 3 22:35:26 2025 +0100
Optimize array_fill_keys() (#20347)
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
```
diff --git a/UPGRADING b/UPGRADING
index 7a3aff95da8..858e1cffa95 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -122,3 +122,6 @@ PHP 8.6 UPGRADE NOTES
- JSON:
. Improve performance of encoding arrays and objects.
+
+- Standard:
+ . Improved performance of array_fill_keys().
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 57020bbcad0..3a501b7f37d 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -473,6 +473,17 @@ static zend_always_inline bool zend_hash_str_exists_ind(const HashTable *ht, con
Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF);
}
+static zend_always_inline zval *zend_symtable_add(HashTable *ht, zend_string *key, zval *pData)
+{
+ zend_ulong idx;
+
+ if (ZEND_HANDLE_NUMERIC(key, idx)) {
+ return zend_hash_index_add(ht, idx, pData);
+ } else {
+ return zend_hash_add(ht, key, pData);
+ }
+}
+
static zend_always_inline zval *zend_symtable_add_new(HashTable *ht, zend_string *key, zval *pData)
{
zend_ulong idx;
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 4097d718990..32d28fe7022 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -2830,16 +2830,19 @@ PHP_FUNCTION(array_fill_keys)
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) {
ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(val);
if (Z_TYPE_P(entry) == IS_LONG) {
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val);
+ zend_hash_index_add(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val);
} else {
zend_string *tmp_key;
zend_string *key = zval_get_tmp_string(entry, &tmp_key);
- zend_symtable_update(Z_ARRVAL_P(return_value), key, val);
+ zend_symtable_add(Z_ARRVAL_P(return_value), key, val);
zend_tmp_string_release(tmp_key);
}
} ZEND_HASH_FOREACH_END();
+
+ if (Z_REFCOUNTED_P(val)) {
+ GC_ADDREF_EX(Z_COUNTED_P(val), zend_hash_num_elements(Z_ARRVAL_P(return_value)));
+ }
}
/* }}} */