From 4a4a71a3b0170330fa365dbcaf68cd4d2e98c274 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Mar 2025 14:10:21 +0100 Subject: [PATCH] Avoid pointless refcounting in array_reduce MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For this script: ```php for ($i=0;$i < 100; $i++) array_reduce(range(1, 100000), fn ($a,$b)=>$a+$b,1); ``` On an i7-4790: ``` Benchmark 1: ./sapi/cli/php reduce_bench.php Time (mean ± σ): 272.0 ms ± 3.7 ms [User: 268.9 ms, System: 2.1 ms] Range (min … max): 268.9 ms … 281.3 ms 11 runs Benchmark 2: ./sapi/cli/php_old reduce_bench.php Time (mean ± σ): 288.2 ms ± 3.5 ms [User: 284.5 ms, System: 2.7 ms] Range (min … max): 285.0 ms … 295.9 ms 10 runs Summary ./sapi/cli/php reduce_bench.php ran 1.06 ± 0.02 times faster than ./sapi/cli/php_old reduce_bench.php ``` On an i7-1185G7: ``` Benchmark 1: ./sapi/cli/php test.php Time (mean ± σ): 189.6 ms ± 3.5 ms [User: 178.5 ms, System: 10.7 ms] Range (min … max): 187.3 ms … 201.6 ms 15 runs Benchmark 2: ./sapi/cli/php_old test.php Time (mean ± σ): 204.2 ms ± 2.9 ms [User: 190.1 ms, System: 13.6 ms] Range (min … max): 200.6 ms … 210.2 ms 14 runs Summary ./sapi/cli/php test.php ran 1.08 ± 0.02 times faster than ./sapi/cli/php_old test.php ``` --- ext/standard/array.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 994e0ad34a8cb..aeaef847dd676 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6437,7 +6437,6 @@ PHP_FUNCTION(array_reduce) zval *input; zval args[2]; zval *operand; - zval retval; zend_fcall_info fci; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; zval *initial = NULL; @@ -6450,8 +6449,7 @@ PHP_FUNCTION(array_reduce) Z_PARAM_ZVAL(initial) ZEND_PARSE_PARAMETERS_END(); - - if (ZEND_NUM_ARGS() > 2) { + if (initial) { ZVAL_COPY(return_value, initial); } else { ZVAL_NULL(return_value); @@ -6466,24 +6464,22 @@ PHP_FUNCTION(array_reduce) return; } - fci.retval = &retval; + fci.retval = return_value; fci.param_count = 2; + fci.params = args; ZEND_HASH_FOREACH_VAL(htbl, operand) { ZVAL_COPY_VALUE(&args[0], return_value); - ZVAL_COPY(&args[1], operand); - fci.params = args; + ZVAL_COPY_VALUE(&args[1], operand); - if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - ZVAL_COPY_VALUE(return_value, &retval); + zend_call_function(&fci, &fci_cache); + zval_ptr_dtor(&args[0]); + + if (EXPECTED(!Z_ISUNDEF_P(return_value))) { if (UNEXPECTED(Z_ISREF_P(return_value))) { zend_unwrap_reference(return_value); } } else { - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); RETURN_NULL(); } } ZEND_HASH_FOREACH_END();