From 1d941986d905f623db4c638451967a1d5a4af6f2 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 20 Oct 2026 22:54:36 +0200 Subject: [PATCH] [perf] Use native instanceof in NodeGroup::isStmtAwareNode isStmtAwareNode() is called per node on the traversal hot path (top call count in a full profile). It used array_any() over STMTS_AWARE with a closure doing a dynamic $node instanceof $class per element - a closure call plus dynamic instanceof for each of 18 classes. Replace with native instanceof via match(true): no per-element closure, no dynamic instanceof, same subclass semantics. bench/node_group_is_stmt_aware_bench.php (non-stmt-aware-heavy node mix): 3.34 -> 0.75 us/call (~4.5x). --- bench/node_group_is_stmt_aware_bench.php | 73 ++++++++++++++++++++++++ src/PhpParser/Enum/NodeGroup.php | 24 +++++++- 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 bench/node_group_is_stmt_aware_bench.php diff --git a/bench/node_group_is_stmt_aware_bench.php b/bench/node_group_is_stmt_aware_bench.php new file mode 100644 index 00000000000..2093b206931 --- /dev/null +++ b/bench/node_group_is_stmt_aware_bench.php @@ -0,0 +1,73 @@ + $node instanceof $stmtAwareClass); + // native instanceof instead of array_any() over STMTS_AWARE - avoids the per-element + // closure call and dynamic instanceof on this hot traversal path; subclass semantics kept + return match (true) { + $node instanceof Block, + $node instanceof Closure, + $node instanceof Case_, + $node instanceof Catch_, + $node instanceof ClassMethod, + $node instanceof Do_, + $node instanceof Else_, + $node instanceof ElseIf_, + $node instanceof Finally_, + $node instanceof For_, + $node instanceof Foreach_, + $node instanceof Function_, + $node instanceof If_, + $node instanceof Namespace_, + $node instanceof TryCatch, + $node instanceof While_, + $node instanceof FileNode, + $node instanceof Declare_ => true, + default => false, + }; } }