Skip to content

Commit cc04158

Browse files
committed
array_unshift: Add fast optimized case for packed arrays
Packed arrays are likely common in this case, as with array_shift which already has a similar optimization. For the following benchmark: ```php <?php for ($i = 0; $i < 10000000; $i++) { $a = [0, 1, 2, 3, 4, 5]; array_unshift($a, -3, -2, -1); } ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php x.php Time (mean ± σ): 753.8 ms ± 23.8 ms [User: 749.8 ms, System: 2.1 ms] Range (min … max): 734.3 ms … 818.6 ms 10 runs Benchmark 2: ./sapi/cli/php_old x.php Time (mean ± σ): 972.5 ms ± 5.0 ms [User: 968.8 ms, System: 1.4 ms] Range (min … max): 967.8 ms … 984.3 ms 10 runs Summary ./sapi/cli/php x.php ran 1.29 ± 0.04 times faster than ./sapi/cli/php_old x.php ```
1 parent 2523491 commit cc04158

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

ext/standard/array.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3750,18 +3750,34 @@ PHP_FUNCTION(array_unshift)
37503750
ZEND_PARSE_PARAMETERS_END();
37513751

37523752
zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + argc, NULL, ZVAL_PTR_DTOR, 0);
3753-
for (uint32_t i = 0; i < argc; i++) {
3754-
Z_TRY_ADDREF(args[i]);
3755-
zend_hash_next_index_insert_new(&new_hash, &args[i]);
3756-
}
37573753

3758-
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
3759-
if (key) {
3760-
zend_hash_add_new(&new_hash, key, value);
3761-
} else {
3762-
zend_hash_next_index_insert_new(&new_hash, value);
3754+
if (HT_IS_PACKED(Z_ARRVAL_P(stack))) {
3755+
zend_hash_real_init_packed(&new_hash);
3756+
3757+
ZEND_HASH_FILL_PACKED(&new_hash) {
3758+
for (uint32_t i = 0; i < argc; i++) {
3759+
Z_TRY_ADDREF(args[i]);
3760+
ZEND_HASH_FILL_ADD(&args[i]);
3761+
}
3762+
3763+
ZEND_HASH_PACKED_FOREACH_VAL(Z_ARRVAL_P(stack), value) {
3764+
ZEND_HASH_FILL_ADD(value);
3765+
} ZEND_HASH_FOREACH_END();
3766+
} ZEND_HASH_FILL_END();
3767+
} else {
3768+
for (uint32_t i = 0; i < argc; i++) {
3769+
Z_TRY_ADDREF(args[i]);
3770+
zend_hash_next_index_insert_new(&new_hash, &args[i]);
37633771
}
3764-
} ZEND_HASH_FOREACH_END();
3772+
3773+
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
3774+
if (key) {
3775+
zend_hash_add_new(&new_hash, key, value);
3776+
} else {
3777+
zend_hash_next_index_insert_new(&new_hash, value);
3778+
}
3779+
} ZEND_HASH_FOREACH_END();
3780+
}
37653781

37663782
if (UNEXPECTED(HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) {
37673783
zend_hash_iterators_advance(Z_ARRVAL_P(stack), argc);

0 commit comments

Comments
 (0)