Commit 2d6b869
authored
zend_vm: Add OPcode specialization for
* zend_vm: Add OPcode specialization for `=== []`
Checking whether an array is empty with a strict comparison against the empty
array is a common pattern in PHP. A GitHub search for `"=== []" language:PHP`
reveals 44k hits. From the set of `!$a`, `count($a) === 0`, `empty($a)` and
`$a === []` it however is also the slowest option.
A test script:
<?php
$variable = array_fill(0, 10, random_int(1, 2));
$f = true;
for ($i = 0; $i < 50_000_000; $i++) {
$isEmpty = $variable === [];
$f = $f && $isEmpty;
}
var_dump($f);
with the `$isEmpty = …;` statement appropriately replaced results in:
Benchmark 1: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 count.php
Time (mean ± σ): 467.6 ms ± 2.3 ms [User: 463.3 ms, System: 3.4 ms]
Range (min … max): 464.6 ms … 473.4 ms 10 runs
Benchmark 2: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 empty.php
Time (mean ± σ): 305.3 ms ± 0.3 ms [User: 302.0 ms, System: 3.1 ms]
Range (min … max): 304.9 ms … 305.7 ms 10 runs
Benchmark 3: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 identical.php
Time (mean ± σ): 630.3 ms ± 3.9 ms [User: 624.8 ms, System: 3.8 ms]
Range (min … max): 627.4 ms … 637.6 ms 10 runs
Benchmark 4: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 not.php
Time (mean ± σ): 311.8 ms ± 3.4 ms [User: 307.9 ms, System: 3.6 ms]
Range (min … max): 308.7 ms … 320.7 ms 10 runs
Summary
sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 empty.php ran
1.02 ± 0.01 times faster than sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 not.php
1.53 ± 0.01 times faster than sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 count.php
2.06 ± 0.01 times faster than sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 identical.php
This patch adds another OPcode specialization for `ZEND_IS_IDENTICAL` that
specifically matches a comparison against the empty array. With this
specialization the `=== []` check becomes the fastest of them all, which is not
surprising given how specific it is:
Benchmark 1: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 count.php
Time (mean ± σ): 384.1 ms ± 2.3 ms [User: 379.3 ms, System: 3.8 ms]
Range (min … max): 382.2 ms … 389.8 ms 10 runs
Benchmark 2: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 empty.php
Time (mean ± σ): 305.8 ms ± 3.2 ms [User: 301.7 ms, System: 3.8 ms]
Range (min … max): 304.4 ms … 314.9 ms 10 runs
Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.
Benchmark 3: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 identical.php
Time (mean ± σ): 293.9 ms ± 2.9 ms [User: 289.7 ms, System: 3.3 ms]
Range (min … max): 291.5 ms … 299.4 ms 10 runs
Benchmark 4: sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 not.php
Time (mean ± σ): 306.8 ms ± 0.4 ms [User: 303.8 ms, System: 2.7 ms]
Range (min … max): 306.3 ms … 307.3 ms 10 runs
Summary
sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 identical.php ran
1.04 ± 0.01 times faster than sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 empty.php
1.04 ± 0.01 times faster than sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 not.php
1.31 ± 0.02 times faster than sapi/cli/php -d zend_extension=modules/opcache.so -d opcache.enable_cli=1 count.php
As a follow-up optimization it might be possible to transform the other
emptiness checks, such as `count($arr) === 0` into `$arr === []` if `$arr` is
known to be `MAY_BE_ARRAY` only.
* zend_vm: Add OPcode specialization for `!== []`
* UPGRADING=== [] (php#18571)1 parent 8e2acc0 commit 2d6b869
File tree
4 files changed
+398
-241
lines changed- Zend
4 files changed
+398
-241
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
516 | 516 | | |
517 | 517 | | |
518 | 518 | | |
| 519 | + | |
519 | 520 | | |
520 | 521 | | |
521 | 522 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10062 | 10062 | | |
10063 | 10063 | | |
10064 | 10064 | | |
| 10065 | + | |
| 10066 | + | |
| 10067 | + | |
| 10068 | + | |
| 10069 | + | |
| 10070 | + | |
| 10071 | + | |
| 10072 | + | |
| 10073 | + | |
| 10074 | + | |
| 10075 | + | |
| 10076 | + | |
| 10077 | + | |
| 10078 | + | |
| 10079 | + | |
| 10080 | + | |
| 10081 | + | |
| 10082 | + | |
| 10083 | + | |
| 10084 | + | |
| 10085 | + | |
| 10086 | + | |
| 10087 | + | |
| 10088 | + | |
| 10089 | + | |
| 10090 | + | |
10065 | 10091 | | |
10066 | 10092 | | |
10067 | 10093 | | |
| |||
0 commit comments