mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Improve performance of array_find() etc (#18157)
This avoids destruction logic for the common case, avoids some copy, and
adds an optimization hint.
For this script:
```php
$array = range(1, 10000);
$result = 0;
for ($i = 0; $i < 5000; $i++) {
$result += array_find($array, static function ($item) {
return $item === 5000;
});
}
var_dump($result);
```
On an intel i7 1185G7:
```
Benchmark 1: ./sapi/cli/php x.php
Time (mean ± σ): 543.7 ms ± 3.8 ms [User: 538.9 ms, System: 4.4 ms]
Range (min … max): 538.4 ms … 552.9 ms 10 runs
Benchmark 2: ./sapi/cli/php_old x.php
Time (mean ± σ): 583.0 ms ± 4.2 ms [User: 578.4 ms, System: 3.4 ms]
Range (min … max): 579.3 ms … 593.9 ms 10 runs
Summary
./sapi/cli/php x.php ran
1.07 ± 0.01 times faster than ./sapi/cli/php_old x.php
```
On an intel i7 4790:
```
Benchmark 1: ./sapi/cli/php x.php
Time (mean ± σ): 828.6 ms ± 4.8 ms [User: 824.4 ms, System: 1.6 ms]
Range (min … max): 822.8 ms … 839.0 ms 10 runs
Benchmark 2: ./sapi/cli/php_old x.php
Time (mean ± σ): 940.1 ms ± 26.4 ms [User: 934.4 ms, System: 2.5 ms]
Range (min … max): 918.0 ms … 981.1 ms 10 runs
Summary
./sapi/cli/php x.php ran
1.13 ± 0.03 times faster than ./sapi/cli/php_old x.php
```
This commit is contained in:
@@ -6509,6 +6509,22 @@ PHP_FUNCTION(array_reduce)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Consumes `zv` */
|
||||
static bool php_is_true(zval *zv)
|
||||
{
|
||||
switch (Z_TYPE_P(zv)) {
|
||||
case IS_TRUE:
|
||||
return true;
|
||||
case IS_FALSE:
|
||||
return false;
|
||||
default: {
|
||||
bool rv = zend_is_true(zv);
|
||||
zval_ptr_dtor(zv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* {{{ Filters elements from the array via the callback. */
|
||||
PHP_FUNCTION(array_filter)
|
||||
{
|
||||
@@ -6571,9 +6587,7 @@ PHP_FUNCTION(array_filter)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
bool retval_true = zend_is_true(&retval);
|
||||
zval_ptr_dtor(&retval);
|
||||
if (!retval_true) {
|
||||
if (!php_is_true(&retval)) {
|
||||
continue;
|
||||
}
|
||||
} else if (!zend_is_true(operand)) {
|
||||
@@ -6597,7 +6611,7 @@ enum php_array_find_result {
|
||||
PHP_ARRAY_FIND_SOME = 1,
|
||||
};
|
||||
|
||||
static enum php_array_find_result php_array_find(const HashTable *array, zend_fcall_info fci, zend_fcall_info_cache fci_cache, zval *result_key, zval *result_value, bool negate_condition)
|
||||
static enum php_array_find_result php_array_find(const HashTable *array, zend_fcall_info fci, zend_fcall_info_cache *fci_cache, zval *result_key, zval *result_value, bool negate_condition)
|
||||
{
|
||||
zend_ulong num_key;
|
||||
zend_string *str_key;
|
||||
@@ -6620,25 +6634,22 @@ static enum php_array_find_result php_array_find(const HashTable *array, zend_fc
|
||||
if (!str_key) {
|
||||
ZVAL_LONG(&args[1], num_key);
|
||||
} else {
|
||||
/* Allows copying the numeric branch, without this branch, into the iteration code
|
||||
* that checks for the packed array flag. */
|
||||
ZEND_ASSUME(!HT_IS_PACKED(array));
|
||||
ZVAL_STR(&args[1], str_key);
|
||||
}
|
||||
|
||||
ZVAL_COPY_VALUE(&args[0], operand);
|
||||
|
||||
zend_result result = zend_call_function(&fci, &fci_cache);
|
||||
zend_result result = zend_call_function(&fci, fci_cache);
|
||||
ZEND_ASSERT(result == SUCCESS);
|
||||
|
||||
if (UNEXPECTED(Z_ISUNDEF(retval))) {
|
||||
return PHP_ARRAY_FIND_EXCEPTION;
|
||||
}
|
||||
|
||||
bool retval_true = zend_is_true(&retval);
|
||||
zval_ptr_dtor(&retval);
|
||||
|
||||
/* This negates the condition, if negate_condition is true. Otherwise it does nothing with `retval_true`. */
|
||||
retval_true ^= negate_condition;
|
||||
|
||||
if (retval_true) {
|
||||
if (php_is_true(&retval) ^ negate_condition) {
|
||||
if (result_value != NULL) {
|
||||
ZVAL_COPY_DEREF(result_value, &args[0]);
|
||||
}
|
||||
@@ -6667,7 +6678,7 @@ PHP_FUNCTION(array_find)
|
||||
Z_PARAM_FUNC(fci, fci_cache)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_array_find(array, fci, fci_cache, NULL, return_value, false);
|
||||
php_array_find(array, fci, &fci_cache, NULL, return_value, false);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -6683,7 +6694,7 @@ PHP_FUNCTION(array_find_key)
|
||||
Z_PARAM_FUNC(fci, fci_cache)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_array_find(array, fci, fci_cache, return_value, NULL, false);
|
||||
php_array_find(array, fci, &fci_cache, return_value, NULL, false);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -6699,7 +6710,7 @@ PHP_FUNCTION(array_any)
|
||||
Z_PARAM_FUNC(fci, fci_cache)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
RETURN_BOOL(php_array_find(array, fci, fci_cache, NULL, NULL, false) == PHP_ARRAY_FIND_SOME);
|
||||
RETURN_BOOL(php_array_find(array, fci, &fci_cache, NULL, NULL, false) == PHP_ARRAY_FIND_SOME);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -6715,7 +6726,7 @@ PHP_FUNCTION(array_all)
|
||||
Z_PARAM_FUNC(fci, fci_cache)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
RETURN_BOOL(php_array_find(array, fci, fci_cache, NULL, NULL, true) == PHP_ARRAY_FIND_NONE);
|
||||
RETURN_BOOL(php_array_find(array, fci, &fci_cache, NULL, NULL, true) == PHP_ARRAY_FIND_NONE);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user