Skip to content

Commit d0bf82f

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 4a98fa1 commit d0bf82f

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
@@ -3743,18 +3743,34 @@ PHP_FUNCTION(array_unshift)
37433743
ZEND_PARSE_PARAMETERS_END();
37443744

37453745
zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + argc, NULL, ZVAL_PTR_DTOR, 0);
3746-
for (uint32_t i = 0; i < argc; i++) {
3747-
Z_TRY_ADDREF(args[i]);
3748-
zend_hash_next_index_insert_new(&new_hash, &args[i]);
3749-
}
37503746

3751-
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
3752-
if (key) {
3753-
zend_hash_add_new(&new_hash, key, value);
3754-
} else {
3755-
zend_hash_next_index_insert_new(&new_hash, value);
3747+
if (HT_IS_PACKED(Z_ARRVAL_P(stack))) {
3748+
zend_hash_real_init_packed(&new_hash);
3749+
3750+
ZEND_HASH_FILL_PACKED(&new_hash) {
3751+
for (uint32_t i = 0; i < argc; i++) {
3752+
Z_TRY_ADDREF(args[i]);
3753+
ZEND_HASH_FILL_ADD(&args[i]);
3754+
}
3755+
3756+
ZEND_HASH_PACKED_FOREACH_VAL(Z_ARRVAL_P(stack), value) {
3757+
ZEND_HASH_FILL_ADD(value);
3758+
} ZEND_HASH_FOREACH_END();
3759+
} ZEND_HASH_FILL_END();
3760+
} else {
3761+
for (uint32_t i = 0; i < argc; i++) {
3762+
Z_TRY_ADDREF(args[i]);
3763+
zend_hash_next_index_insert_new(&new_hash, &args[i]);
37563764
}
3757-
} ZEND_HASH_FOREACH_END();
3765+
3766+
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
3767+
if (key) {
3768+
zend_hash_add_new(&new_hash, key, value);
3769+
} else {
3770+
zend_hash_next_index_insert_new(&new_hash, value);
3771+
}
3772+
} ZEND_HASH_FOREACH_END();
3773+
}
37583774

37593775
if (UNEXPECTED(HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) {
37603776
zend_hash_iterators_advance(Z_ARRVAL_P(stack), argc);

0 commit comments

Comments
 (0)