Skip to content

Commit e034b69

Browse files
authored
Optimize SplFixedArray::fromArray() for packed arrays (#18196)
If the array is packed, then we don't have to loop to get the highest index. For this script: ```php $array = range(1, 100); for ($i=0;$i<1000000;$i++) { SplFixedArray::fromArray($array); } ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php spl.php Time (mean ± σ): 376.5 ms ± 2.0 ms [User: 372.1 ms, System: 2.6 ms] Range (min … max): 373.7 ms … 379.5 ms 10 runs Benchmark 2: ./sapi/cli/php_old spl.php Time (mean ± σ): 511.6 ms ± 1.9 ms [User: 508.0 ms, System: 2.3 ms] Range (min … max): 509.2 ms … 515.1 ms 10 runs Summary ./sapi/cli/php spl.php ran 1.36 ± 0.01 times faster than ./sapi/cli/php_old spl.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php spl.php Time (mean ± σ): 250.4 ms ± 3.5 ms [User: 246.6 ms, System: 2.6 ms] Range (min … max): 247.0 ms … 258.5 ms 11 runs Benchmark 2: ./sapi/cli/php_old spl.php Time (mean ± σ): 328.4 ms ± 1.0 ms [User: 324.4 ms, System: 3.8 ms] Range (min … max): 327.5 ms … 331.0 ms 10 runs Summary ./sapi/cli/php spl.php ran 1.31 ± 0.02 times faster than ./sapi/cli/php_old spl.php ``` Bonus: this also decreases the code size of the function.
1 parent f056636 commit e034b69

File tree

1 file changed

+20
-13
lines changed

1 file changed

+20
-13
lines changed

ext/spl/spl_fixedarray.c

+20-13
Original file line numberDiff line numberDiff line change
@@ -733,22 +733,29 @@ PHP_METHOD(SplFixedArray, fromArray)
733733
zend_ulong num_index, max_index = 0;
734734
zend_long tmp;
735735

736-
ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(data), num_index, str_index) {
737-
if (str_index != NULL || (zend_long)num_index < 0) {
738-
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array must contain only positive integer keys");
736+
if (HT_IS_PACKED(Z_ARRVAL_P(data))) {
737+
/* If there are no holes, then nNumUsed is the number of elements.
738+
* If there are holes, then nNumUsed is the index of the last element. */
739+
tmp = Z_ARRVAL_P(data)->nNumUsed;
740+
} else {
741+
ZEND_HASH_MAP_FOREACH_KEY(Z_ARRVAL_P(data), num_index, str_index) {
742+
if (str_index != NULL || (zend_long)num_index < 0) {
743+
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array must contain only positive integer keys");
744+
RETURN_THROWS();
745+
}
746+
747+
if (num_index > max_index) {
748+
max_index = num_index;
749+
}
750+
} ZEND_HASH_FOREACH_END();
751+
752+
tmp = max_index + 1;
753+
if (tmp <= 0) {
754+
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "integer overflow detected");
739755
RETURN_THROWS();
740756
}
741-
742-
if (num_index > max_index) {
743-
max_index = num_index;
744-
}
745-
} ZEND_HASH_FOREACH_END();
746-
747-
tmp = max_index + 1;
748-
if (tmp <= 0) {
749-
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "integer overflow detected");
750-
RETURN_THROWS();
751757
}
758+
752759
spl_fixedarray_init(&array, tmp);
753760

754761
ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data), num_index, element) {

0 commit comments

Comments
 (0)