Skip to content

Commit 5d24c8b

Browse files
ext/standard: Optimize array_column() (#23786)
Just move some numeric-string key normalization stuff out of the main loop. Also return early for empty input. Co-authored-by: David CARLIER <devnexen@gmail.com>
1 parent 3c857cc commit 5d24c8b

1 file changed

Lines changed: 36 additions & 13 deletions

File tree

ext/standard/array.c

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4593,7 +4593,7 @@ PHP_FUNCTION(array_count_values)
45934593
}
45944594
/* }}} */
45954595

4596-
static inline zval *array_column_fetch_prop(zval *data, zend_string *name_str, zend_long name_long, void **cache_slot, zval *rv) /* {{{ */
4596+
static inline zval *array_column_fetch_prop(zval *data, zend_string *name_str, zend_long name_long, bool is_string_key, void **cache_slot, zval *rv) /* {{{ */
45974597
{
45984598
zval *prop = NULL;
45994599

@@ -4620,9 +4620,8 @@ static inline zval *array_column_fetch_prop(zval *data, zend_string *name_str, z
46204620
}
46214621
zend_string_release(tmp_str);
46224622
} else if (Z_TYPE_P(data) == IS_ARRAY) {
4623-
/* Name is a string */
4624-
if (name_str != NULL) {
4625-
prop = zend_symtable_find(Z_ARRVAL_P(data), name_str);
4623+
if (is_string_key) {
4624+
prop = zend_hash_find(Z_ARRVAL_P(data), name_str);
46264625
} else {
46274626
prop = zend_hash_index_find(Z_ARRVAL_P(data), name_long);
46284627
}
@@ -4656,38 +4655,62 @@ PHP_FUNCTION(array_column)
46564655
Z_PARAM_STR_OR_LONG_OR_NULL(index_str, index_long, index_is_null)
46574656
ZEND_PARSE_PARAMETERS_END();
46584657

4659-
void* cache_slot_column[3] = { NULL, NULL, NULL };
4660-
void* cache_slot_index[3] = { NULL, NULL, NULL };
4658+
uint32_t num_elements = zend_hash_num_elements(input);
4659+
if (num_elements == 0) {
4660+
RETURN_EMPTY_ARRAY();
4661+
}
4662+
4663+
if (column_is_null && index_is_null) {
4664+
array_init_size(return_value, num_elements);
4665+
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
4666+
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
4667+
ZEND_HASH_FOREACH_VAL(input, data) {
4668+
ZVAL_DEREF(data);
4669+
Z_TRY_ADDREF_P(data);
4670+
ZEND_HASH_FILL_ADD(data);
4671+
} ZEND_HASH_FOREACH_END();
4672+
} ZEND_HASH_FILL_END();
4673+
return;
4674+
}
4675+
4676+
/* Normalize array keys once, retaining the original names for object properties. */
4677+
zend_ulong column_index = (zend_ulong) column_long;
4678+
bool column_is_string_key = column_str && !ZEND_HANDLE_NUMERIC(column_str, column_index);
4679+
column_long = (zend_long) column_index;
4680+
void *cache_slot_column[3] = { NULL, NULL, NULL };
46614681

4662-
array_init_size(return_value, zend_hash_num_elements(input));
46634682
/* Index param is not passed */
46644683
if (index_is_null) {
4684+
array_init_size(return_value, num_elements);
46654685
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
46664686
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
46674687
ZEND_HASH_FOREACH_VAL(input, data) {
46684688
ZVAL_DEREF(data);
4669-
if (column_is_null) {
4670-
Z_TRY_ADDREF_P(data);
4671-
colval = data;
4672-
} else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) {
4689+
if ((colval = array_column_fetch_prop(data, column_str, column_long, column_is_string_key, cache_slot_column, &rv)) == NULL) {
46734690
continue;
46744691
}
46754692
ZEND_HASH_FILL_ADD(colval);
46764693
} ZEND_HASH_FOREACH_END();
46774694
} ZEND_HASH_FILL_END();
46784695
} else {
4696+
zend_ulong index = (zend_ulong) index_long;
4697+
bool index_is_string_key = index_str && !ZEND_HANDLE_NUMERIC(index_str, index);
4698+
index_long = (zend_long) index;
4699+
void *cache_slot_index[3] = { NULL, NULL, NULL };
4700+
4701+
array_init_size(return_value, num_elements);
46794702
ZEND_HASH_FOREACH_VAL(input, data) {
46804703
ZVAL_DEREF(data);
46814704

46824705
if (column_is_null) {
46834706
Z_TRY_ADDREF_P(data);
46844707
colval = data;
4685-
} else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) {
4708+
} else if ((colval = array_column_fetch_prop(data, column_str, column_long, column_is_string_key, cache_slot_column, &rv)) == NULL) {
46864709
continue;
46874710
}
46884711

46894712
zval rv;
4690-
zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv);
4713+
zval *keyval = array_column_fetch_prop(data, index_str, index_long, index_is_string_key, cache_slot_index, &rv);
46914714
if (keyval) {
46924715
array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval);
46934716
zval_ptr_dtor(colval);

0 commit comments

Comments
 (0)