#
1e7aac31 |
| 13-Jun-2024 |
Tim Düsterhus |
zend_compile: Optimize `sprintf()` into a rope (#14546) * zend_compile: Add `zend_compile_rope_finalize()` This just extracts the implementation as-is into a dedicated function to m
zend_compile: Optimize `sprintf()` into a rope (#14546) * zend_compile: Add `zend_compile_rope_finalize()` This just extracts the implementation as-is into a dedicated function to make it reusable in preparation of a future commit. * zend_compile: Use clearer parameter names for `zend_compile_rope_finalize()` * zend_compile: Fix `zend_compile_rope_finalize()` for ropes containing a single constant string Without this Opcache will trigger a use-after-free in `zend_optimizer_compact_literals()`. Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com> * zend_compile: Optimize `sprintf()` into a rope This optimization will compile `sprintf()` using only `%s` placeholders into a rope at compile time, effectively making those calls equivalent to the use of string interpolation, with the added benefit of supporting arbitrary expressions instead of just expressions starting with a `$`. For a synthetic test using: <?php $a = 'foo'; $b = 'bar'; for ($i = 0; $i < 100_000_000; $i++) { sprintf("%s-%s", $a, $b); } This optimization yields a 2.1× performance improvement: $ hyperfine 'sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php' \ '/tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php' Benchmark 1: sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php Time (mean ± σ): 1.869 s ± 0.033 s [User: 1.865 s, System: 0.003 s] Range (min … max): 1.840 s … 1.945 s 10 runs Benchmark 2: /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php Time (mean ± σ): 4.011 s ± 0.034 s [User: 4.006 s, System: 0.005 s] Range (min … max): 3.964 s … 4.079 s 10 runs Summary sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php ran 2.15 ± 0.04 times faster than /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php This optimization comes with a small and probably insignificant behavioral change: If one of the values cannot be (cleanly) converted to a string, for example when attempting to insert an object that is not `Stringable`, the resulting Exception will naturally not show the `sprintf()` call in the resulting stack trace, because there is no call to `sprintf()`. Nevertheless it will correctly point out the line of the `sprintf()` call as the source of the Exception, pointing the user towards the correct location. * zend_compile: Eagerly handle empty format strings in `sprintf()` optimization * zend_compile: Add additional explanatory comments to zend_compile_func_sprintf() * Add zero-argument test to sprintf_rope_optimization_001.phpt --------- Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
show more ...
|