mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
![]() During the Doctrine Core Team Meetup 2024 the Doctrine team investigated the performance overhead of using `setRawValueWithoutLazyInitialization()` instead of `setValue()` and came to the surprising conclusion that `setRawValueWithoutLazyInitialization()` outperformed `setValue()`, despite doing more work. These two scripts are used as the benchmark: <?php class Foo { public $id; public $foo1; public $foo2; public $foo3; public $foo4; } $reflection = new ReflectionClass(Foo::class); $properties = $reflection->getProperties(); for ($i = 0; $i < 1000000; $i++) { $foo = new Foo(); foreach ($properties as $property) { $property->setValue($foo, 1); } } and <?php class Foo { public $id; public $foo1; public $foo2; public $foo3; public $foo4; } $reflection = new ReflectionClass(Foo::class); $properties = $reflection->getProperties(); for ($i = 0; $i < 1000000; $i++) { $foo = new Foo(); foreach ($properties as $property) { $property->setRawValueWithoutLazyInitialization($foo, 1); } } Benchmarking these with a current git master shows that `setValue()` is 50% slower: $ hyperfine -L script setValue,setRawValueWithoutLazyInitialization '/tmp/php-before /tmp/test/{script}.php' Benchmark 1: /tmp/php-before /tmp/test/setValue.php Time (mean ± σ): 216.0 ms ± 5.8 ms [User: 212.0 ms, System: 3.7 ms] Range (min … max): 208.2 ms … 225.3 ms 13 runs Benchmark 2: /tmp/php-before /tmp/test/setRawValueWithoutLazyInitialization.php Time (mean ± σ): 145.6 ms ± 3.6 ms [User: 141.6 ms, System: 3.8 ms] Range (min … max): 140.4 ms … 152.8 ms 20 runs Summary /tmp/php-before /tmp/test/setRawValueWithoutLazyInitialization.php ran 1.48 ± 0.05 times faster than /tmp/php-before /tmp/test/setValue.php Looking into the “why” revealed that the `setValue()` script spent quite some time in `zend_parse_parameters()`. A 50% overhead can be significant, given that `setValue()` is commonly called several thousand times in a single request when using Doctrine. This commit changes the non-static property case of `setValue()` to make use of the fast parameter parsing API and adjusts `getValue()` for consistency. The resulting comparison shows that both `setValue()` and `setRawValueWithoutLazyInitialization()` are now (almost) equal: $ hyperfine -L script setValue,setRawValueWithoutLazyInitialization 'sapi/cli/php /tmp/test/{script}.php' Benchmark 1: sapi/cli/php /tmp/test/setValue.php Time (mean ± σ): 143.0 ms ± 6.4 ms [User: 139.4 ms, System: 3.4 ms] Range (min … max): 134.8 ms … 157.7 ms 18 runs Benchmark 2: sapi/cli/php /tmp/test/setRawValueWithoutLazyInitialization.php Time (mean ± σ): 147.0 ms ± 5.5 ms [User: 143.0 ms, System: 3.6 ms] Range (min … max): 139.9 ms … 159.8 ms 19 runs Summary sapi/cli/php /tmp/test/setValue.php ran 1.03 ± 0.06 times faster than sapi/cli/php /tmp/test/setRawValueWithoutLazyInitialization.php |
||
---|---|---|
.. | ||
tests | ||
config.m4 | ||
config.w32 | ||
CREDITS | ||
php_reflection.c | ||
php_reflection.h | ||
php_reflection.stub.php | ||
php_reflection_arginfo.h |