#
2c5ed50d |
| 17-Jun-2024 |
Tim Düsterhus |
zend_compile: Add support for `%d` to `sprintf()` optimization (#14561) * zend_compile: Rename `string_placeholder_count` to `placeholder_count` in `zend_compile_func_sprintf()` Thi
zend_compile: Add support for `%d` to `sprintf()` optimization (#14561) * zend_compile: Rename `string_placeholder_count` to `placeholder_count` in `zend_compile_func_sprintf()` This is intended to make the diff of a follow-up commit smaller. * zend_compile: Add support for `%d` to `sprintf()` optimization This extends the existing `sprintf()` optimization by support for the `%d` placeholder, which effectively equivalent to an `(int)` cast followed by a `(string)` cast. For a synthetic test using: <?php $a = 'foo'; $b = 42; for ($i = 0; $i < 100_000_000; $i++) { sprintf("%s-%d", $a, $b); } This optimization yields a 1.3× 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 ± σ): 3.296 s ± 0.094 s [User: 3.287 s, System: 0.005 s] Range (min … max): 3.213 s … 3.527 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.300 s ± 0.025 s [User: 4.290 s, System: 0.007 s] Range (min … max): 4.266 s … 4.334 s 10 runs Summary sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php ran 1.30 ± 0.04 times faster than /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php * Fix sprintf_rope_optimization_003.phpt test expecation for 32-bit integers * zend_compile: Indent switch-case labels in zend_compile_func_sprintf() * Add GMP test to sprintf() rope optimization * Add `%s` test case to sprintf() GMP test
show more ...
|
#
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 ...
|