Skip to content

Conversation

@jorgsowa
Copy link
Contributor

Added checks for packed array inside function _php_search_array that is used by in_array() and array_search().

Function in_array() is used frequently with lists, and this modification improves the performance.

For array_search() in all cases the diference is negligible.

+-----------+------------------+--------+--------------------------------------+
| arraySize | randomKeysSize   | strict | Result                               |
+-----------+------------------+--------+--------------------------------------+
| 5000      | 5000             | false  | master 1.00 ± 0.00× faster than new  |
| 5000      | 5000             | true   | master 1.00 ± 0.00× faster than new  |
| 5         | 5                | true   | master 1.00 ± 0.09× faster than new  |
| 5         | 5                | false  | master 1.00 ± 0.09× faster than new  |
+-----------+------------------+--------+--------------------------------------+

For in_array() bigger the array, faster the execution.

| arraySize | randomKeysSize | packed | valueType | strict | Result (new vs master)    
|-----------|----------------|--------|-----------|--------|----------------------------------
| 500,000   | 100            | yes    | int       | false  | 1.32 ± 0.01 × faster     
| 500,000   | 100            | yes    | int       | true   | 1.19 ± 0.02 × faster        
| 50,000    | 100            | yes    | mixed     | false  | 1.07 ± 0.16 × faster         
| 500,000   | 100            | yes    | mixed     | true   | 1.19 ± 0.01 × faster       
| 500,000   | 100            | yes    | string    | false  | 1.11 ± 0.01 × faster     
| 500,000   | 100            | yes    | string    | true   | 1.08 ± 0.01 × faster   
| 50,000    | 100            | no     | string    | false  | 1.01 ± 0.01 × faster            
| 50,000    | 100            | no     | string    | true   | 1.00 ± 0.01 × faster       
| 500       | 100            | yes    | int       | false  | 1.05 ± 0.12 x faster          
| 500       | 100            | yes    | int       | true   | 1.05 ± 0.06 x faster   
| 500       | 100            | yes    | mixed     | false  | 1.03 ± 0.01 x faster   
| 500       | 100            | yes    | mixed     | true   | 1.08 ± 0.30 x faster            
| 500       | 100            | yes    | string    | false  | 1.08 ± 0.15 x faster        
| 500       | 100            | yes    | string    | true   | 1.04 ± 0.03 x faster      
| 500       | 100            | no     | string    | false  | 1.01 ± 0.18 x faster           
| 500       | 100            | no     | string    | true   | 1.01 ± 0.14 x slower       
| 5         | 5              | yes    | mixed     | true   | 1.01 ± 0.23 x faster (10000 loops)
| 5         | 5              | no     | mixed     | true   | 1.01 ± 0.05 x faster (10000 loops)

Benchmark code
<?php

$arraySize = 100;
$randomKeysSize = 100;
$isPacked = true;
$valueType = 0; // 0 - only strings, 1 - only integers, 2 - string/int 50/50
$strict = false;
$in_array = true;

$array = [];
for ($i = 0; $i < $arraySize; $i++) {
    if($isPacked) {
        $array[] = ($valueType === 0 || $i % $valueType == 1) ? "String $i" : $i;
    } else {
        $array["key_$i"] = "String $i";
    }
}

mt_srand(1234);
$randomKeys = array_rand($array, $randomKeysSize);
$values = array_map(fn($key) => $array[$key], $randomKeys);

for ($i = 0; $i < 100; $i++) {
    foreach ($values as $value) {
        if($in_array) {
            in_array($value, $array, $strict);
        } else {
            array_search($value, $array, $strict);
        }
    }
}

Command I used for comparison:
hyperfine --warmup 3 "sapi/cli/php_master test_in_array.php" "sapi/cli/php test_in_array.php"

Must be merged after merging the extended tests:

}
} ZEND_HASH_FOREACH_END();
} else {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can replace all of these with ZEND_HASH_MAP_FOREACH_KEY_VAL().

} ZEND_HASH_FOREACH_END();
} else {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Keep { on the same line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants