Elide the type check on typed property writes when the value type is statically proven#22347
Elide the type check on typed property writes when the value type is statically proven#22347azjezz wants to merge 3 commits into
Conversation
Signed-off-by: azjezz <azjezz@protonmail.com>
1bbd75c to
faa7adc
Compare
Signed-off-by: azjezz <azjezz@protonmail.com>
| @@ -14989,7 +14994,7 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, | |||
| ir_END_list(slow_inputs); | |||
| ir_IF_TRUE(if_def); | |||
| } | |||
| if (ZEND_TYPE_IS_SET(prop_info->type)) { | |||
| if (ZEND_TYPE_IS_SET(prop_info->type) && !skip_type_check) { | |||
There was a problem hiding this comment.
I couldn't verify this locally. and honestly not sure about it..
Signed-off-by: azjezz <azjezz@protonmail.com>
|
This PR implements #13100. I am suprised this PR only improves the performance by 0.04% on Symfony demo. I would expect more performance gain. Does this PR really drops most of the type checks? |
|
@mvorisek Sorry did not see the open issue for this! As for Symfony, honestly no idea, haven't benchmarked it. It does remove type checks for cases that i have tested. |
|
I agree, a statistic of how many type checks in something like Symfony Demo can be elided would be nice. The instruction count difference is effectively nonexistent, so maybe it doesn't work as expected. |
|
@iluuu1994 I don't have Symfony Demo set up (and I'm not sure of the right way to wire it up for this), also I'm on macOS, so I can't give you a perf/valgrind hardware instruction count. But I think a direct count of elided checks is actually more to the point than instruction count, so I instrumented for that and ran it on a few real suites. I put a counter inside
So on real test code it elides roughly half to two-thirds of all typed-property type checks. So the pass fires correctly. Wall time (
I think this explains the "instruction count is effectively non existent" observation without it meaning the optimization doesn't work
To reproduce: the <?php
final class Point {
public int $x = 0;
public int $y = 0;
public function set(int $x, int $y): void { $this->x = $x; $this->y = $y; }
}
$p = new Point();
for ($i = 0; $i < 20_000_000; $i++) { $p->set($i, $i + 1); }The PSL suites are on the monorepo, Although, I do expect there to be some perf wins in Doctrine during hydration ( and therefore Symfony ). |
Assigning to a typed property runs
zend_assign_to_typed_prop()on every write, azend_never_inlinecall that verifies (and may coerce) the value against the property type. When the optimizer can already prove the value satisfies the property type with no coercion, that check is pure overhead.This is extremely common: constructor property promotion, plain
$this->x = $xfrom typed parameters, and fluent setters all hit it on every call. Neither the DFA optimizer nor the JIT elided it before.