Skip to content

Commit 8af7046

Browse files
committed
Optimize array_slice for packed arrays with large offsets
If the offset is 100000, and there are no gaps in the packed array, then advance the pointer once by 100000, instead of looping and skipping 100000 times.
1 parent 284e993 commit 8af7046

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

ext/standard/array.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3511,11 +3511,21 @@ PHP_FUNCTION(array_slice)
35113511
if (HT_IS_PACKED(Z_ARRVAL_P(input)) &&
35123512
(!preserve_keys ||
35133513
(offset == 0 && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(input))))) {
3514+
3515+
zend_bool can_skip = offset > 0 && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(input));
35143516
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
35153517
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
35163518
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
35173519
pos++;
35183520
if (pos <= offset) {
3521+
if (can_skip) {
3522+
/* Optimization: Instead of advancing offset times over a packed array without holes, */
3523+
/* advance just once (useful when offset is a million). */
3524+
/* The above code checked that the offset was between 0 and the length of the array (inclusive). */
3525+
/* TODO: Better abstraction to advance hash pointer in ZEND_HASH_FOREACH? */
3526+
_p += (offset - pos);
3527+
pos = offset;
3528+
}
35193529
continue;
35203530
}
35213531
if (pos > offset + length) {

0 commit comments

Comments
 (0)