|
| 1 | +<?php |
| 2 | + |
| 3 | +declare(strict_types=1); |
| 4 | + |
| 5 | +/** |
| 6 | + * Benchmark for NodeGroup::isStmtAwareNode(). |
| 7 | + * |
| 8 | + * Called per node on the traversal hot path (top call count in a full profile). It previously used |
| 9 | + * array_any() over the STMTS_AWARE class list with a closure doing a dynamic `$node instanceof $class` |
| 10 | + * per element. The change uses native instanceof via match(true): no per-element closure call, no |
| 11 | + * dynamic instanceof, same subclass semantics. |
| 12 | + * |
| 13 | + * This bench calls it over a realistic node mix - mostly non-stmt-aware nodes (the worst case, which |
| 14 | + * exhausts every instanceof) plus a couple of matches. |
| 15 | + * |
| 16 | + * Run on both branches to compare: |
| 17 | + * php bench/node_group_is_stmt_aware_bench.php |
| 18 | + * |
| 19 | + * Reports CPU time (user+sys) and wall time; CPU is the reliable metric, wall is noisy under |
| 20 | + * concurrent load. |
| 21 | + */ |
| 22 | + |
| 23 | +use PhpParser\Node\Expr\Variable; |
| 24 | +use PhpParser\Node\Identifier; |
| 25 | +use PhpParser\Node\Scalar\String_; |
| 26 | +use PhpParser\Node\Stmt\ClassMethod; |
| 27 | +use PhpParser\Node\Stmt\If_; |
| 28 | +use Rector\PhpParser\Enum\NodeGroup; |
| 29 | + |
| 30 | +require __DIR__ . '/../vendor/autoload.php'; |
| 31 | + |
| 32 | +const REPEAT = 300000; |
| 33 | + |
| 34 | +$nodes = []; |
| 35 | +for ($i = 0; $i < 20; ++$i) { |
| 36 | + $nodes[] = new Variable('x'); |
| 37 | + $nodes[] = new String_('s'); |
| 38 | + $nodes[] = new Identifier('id'); |
| 39 | +} |
| 40 | + |
| 41 | +$nodes[] = new ClassMethod('m'); |
| 42 | +$nodes[] = new If_(new Variable('c')); |
| 43 | + |
| 44 | +$cpuSeconds = static function (): float { |
| 45 | + $usage = getrusage(); |
| 46 | + return $usage['ru_utime.tv_sec'] + $usage['ru_utime.tv_usec'] / 1_000_000 |
| 47 | + + $usage['ru_stime.tv_sec'] + $usage['ru_stime.tv_usec'] / 1_000_000; |
| 48 | +}; |
| 49 | + |
| 50 | +$run = static function () use ($nodes): void { |
| 51 | + foreach ($nodes as $node) { |
| 52 | + NodeGroup::isStmtAwareNode($node); |
| 53 | + } |
| 54 | +}; |
| 55 | + |
| 56 | +// warm up |
| 57 | +$run(); |
| 58 | + |
| 59 | +$wallStart = microtime(true); |
| 60 | +$cpuStart = $cpuSeconds(); |
| 61 | + |
| 62 | +for ($repeat = 0; $repeat < REPEAT; ++$repeat) { |
| 63 | + $run(); |
| 64 | +} |
| 65 | + |
| 66 | +$cpu = $cpuSeconds() - $cpuStart; |
| 67 | +$wall = microtime(true) - $wallStart; |
| 68 | + |
| 69 | +$totalCalls = REPEAT * count($nodes); |
| 70 | + |
| 71 | +printf('nodes: %d, repeats: %d, calls: %d%s', count($nodes), REPEAT, $totalCalls, PHP_EOL); |
| 72 | +printf('CPU: %.4f s (%.4f us/call)%s', $cpu, $cpu / $totalCalls * 1_000_000, PHP_EOL); |
| 73 | +printf('wall: %.4f s%s', $wall, PHP_EOL); |
0 commit comments