diff --git a/bench/node_comparator_short_circuit_bench.php b/bench/node_comparator_short_circuit_bench.php new file mode 100644 index 00000000000..06a5bba3ada --- /dev/null +++ b/bench/node_comparator_short_circuit_bench.php @@ -0,0 +1,84 @@ +create(); + +/** @var NodeComparator $nodeComparator */ +$nodeComparator = $rectorConfig->make(NodeComparator::class); + +// realistic blend of pairs; most are unequal, the common hot-path case +$pairs = [ + // null operand - newly short-circuited + [new Variable('value'), null], + [null, new String_('name')], + // different class single nodes - newly short-circuited + [new Variable('value'), new String_('value')], + [new Identifier('foo'), new LNumber(1)], + [new String_('a'), new Variable('a')], + // same class, unequal - unchanged (still printed) + [new Variable('first'), new Variable('second')], + [new String_('alpha'), new String_('beta')], + // same class, equal - unchanged (still printed) + [new Variable('same'), new Variable('same')], + [new Identifier('id'), new Identifier('id')], +]; + +$cpuSeconds = static function (): float { + $usage = getrusage(); + return $usage['ru_utime.tv_sec'] + $usage['ru_utime.tv_usec'] / 1_000_000 + + $usage['ru_stime.tv_sec'] + $usage['ru_stime.tv_usec'] / 1_000_000; +}; + +$run = static function () use ($nodeComparator, $pairs): void { + foreach ($pairs as [$first, $second]) { + $nodeComparator->areNodesEqual($first, $second); + } +}; + +// warm up +$run(); + +$wallStart = microtime(true); +$cpuStart = $cpuSeconds(); + +for ($repeat = 0; $repeat < REPEAT; ++$repeat) { + $run(); +} + +$cpu = $cpuSeconds() - $cpuStart; +$wall = microtime(true) - $wallStart; + +$totalCalls = REPEAT * count($pairs); + +printf('pairs: %d, repeats: %d, calls: %d%s', count($pairs), REPEAT, $totalCalls, PHP_EOL); +printf('CPU: %.4f s (%.4f us/call)%s', $cpu, $cpu / $totalCalls * 1_000_000, PHP_EOL); +printf('wall: %.4f s%s', $wall, PHP_EOL); diff --git a/src/PhpParser/Comparing/NodeComparator.php b/src/PhpParser/Comparing/NodeComparator.php index b944e1da94c..918117e680d 100644 --- a/src/PhpParser/Comparing/NodeComparator.php +++ b/src/PhpParser/Comparing/NodeComparator.php @@ -34,6 +34,10 @@ public function printWithoutComments(Node|array|null $node): string */ public function areNodesEqual(Node|array|null $firstNode, Node|array|null $secondNode): bool { + if ($firstNode === null || $secondNode === null) { + return false; + } + if ($firstNode instanceof Node && ! $secondNode instanceof Node) { return false; } @@ -47,6 +51,10 @@ public function areNodesEqual(Node|array|null $firstNode, Node|array|null $secon } if (! is_array($secondNode)) { + if ($firstNode::class !== $secondNode::class) { + return false; + } + return $this->printWithoutComments($firstNode) === $this->printWithoutComments($secondNode); }