Skip to content

[perf] Skip ancestor reflection when no parent:: call to trim - #8707

Merged
TomasVotruba merged 1 commit into
mainfrom
skip-ancestors-without-parent-call
Oct 19, 2026
Merged

TomasVotruba merged 1 commit into
mainfrom
skip-ancestors-without-parent-call

Conversation

@TomasVotruba

Copy link
Copy Markdown
Member

RemoveArgumentFromDefaultParentCallRector subscribes to Class_. For every class that extends a parent it resolved the class reflection and walked getAncestors() - native reflection over the whole ancestor chain - before checking whether the class body even contains a parent:: call to trim. A subclass that never calls parent:: (the common case) paid for that ancestor lookup only to find nothing to do.

A cheap AST pre-scan (hasParentStaticCall) now bails before resolveClassReflection()/getAncestors() when no non-private, non-abstract method body holds a parent:: static call. It mirrors the guards the main loop already applies, so it never skips a class the rule would have changed.

Behavior unchanged - all 5 fixtures pass.

A standalone bench is included (bench/remove_argument_from_default_parent_call_bench.php), driving refactor() over 150 subclasses that extend a parent but never call parent::. CPU per call, averaged, two runs each:

CPU us/call
before 2.66
after 0.87

~3x faster on that hot path. Run php bench/remove_argument_from_default_parent_call_bench.php on each branch to reproduce.

@TomasVotruba
TomasVotruba merged commit 2999ab8 into main Oct 19, 2026
49 checks passed
@TomasVotruba
TomasVotruba deleted the skip-ancestors-without-parent-call branch October 19, 2026 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant