|
| 1 | +<?php |
| 2 | + |
| 3 | +require_once __DIR__ . '/shared.php'; |
| 4 | + |
| 5 | +$storeResult = ($argv[1] ?? 'false') === 'true'; |
| 6 | +$phpCgi = $argv[2] ?? dirname(PHP_BINARY) . '/php-cgi'; |
| 7 | +if (!file_exists($phpCgi)) { |
| 8 | + fwrite(STDERR, "php-cgi not found\n"); |
| 9 | + exit(1); |
| 10 | +} |
| 11 | + |
| 12 | +function main() { |
| 13 | + global $storeResult; |
| 14 | + |
| 15 | + $data = []; |
| 16 | + $data['Zend/bench.php'] = runBench(false); |
| 17 | + $data['Zend/bench.php JIT'] = runBench(true); |
| 18 | + $data['Symfony Demo 2.2.3'] = runSymfonyDemo(false); |
| 19 | + $data['Symfony Demo 2.2.3 JIT'] = runSymfonyDemo(true); |
| 20 | + $data['Wordpress 6.2'] = runWordpress(false); |
| 21 | + $data['Wordpress 6.2 JIT'] = runWordpress(true); |
| 22 | + $result = json_encode($data, JSON_PRETTY_PRINT) . "\n"; |
| 23 | + |
| 24 | + fwrite(STDOUT, $result); |
| 25 | + |
| 26 | + if ($storeResult) { |
| 27 | + storeResult($result); |
| 28 | + } |
| 29 | +} |
| 30 | + |
| 31 | +function storeResult(string $result) { |
| 32 | + $repo = __DIR__ . '/repos/data'; |
| 33 | + cloneRepo($repo, 'git@github.com:php/benchmarking-data.git'); |
| 34 | + |
| 35 | + $commitHash = getPhpSrcCommitHash(); |
| 36 | + $dir = $repo . '/' . substr($commitHash, 0, 2) . '/' . $commitHash; |
| 37 | + $summaryFile = $dir . '/summary.json'; |
| 38 | + if (!is_dir($dir)) { |
| 39 | + mkdir($dir, 0755, true); |
| 40 | + } |
| 41 | + file_put_contents($summaryFile, $result); |
| 42 | +} |
| 43 | + |
| 44 | +function getPhpSrcCommitHash(): string { |
| 45 | + $result = runCommand(['git', 'log', '--pretty=format:%H', '-n', '1'], dirname(__DIR__)); |
| 46 | + return $result->stdout; |
| 47 | +} |
| 48 | + |
| 49 | +function runBench(bool $jit): array { |
| 50 | + return runValgrindPhpCgiCommand([dirname(__DIR__) . '/Zend/bench.php'], jit: $jit); |
| 51 | +} |
| 52 | + |
| 53 | +function runSymfonyDemo(bool $jit): array { |
| 54 | + $dir = __DIR__ . '/repos/symfony-demo-2.2.3'; |
| 55 | + cloneRepo($dir, 'https://github.com/php/benchmarking-symfony-demo-2.2.3.git'); |
| 56 | + runPhpCommand([$dir . '/bin/console', 'cache:clear']); |
| 57 | + runPhpCommand([$dir . '/bin/console', 'cache:warmup']); |
| 58 | + return runValgrindPhpCgiCommand([$dir . '/public/index.php'], cwd: $dir, jit: $jit, warmup: 50); |
| 59 | +} |
| 60 | + |
| 61 | +function runWordpress(bool $jit): array { |
| 62 | + $dir = __DIR__ . '/repos/wordpress-6.2'; |
| 63 | + cloneRepo($dir, 'https://github.com/php/benchmarking-wordpress-6.2.git'); |
| 64 | + |
| 65 | + /* FIXME: It might be better to use a stable version of PHP for this command because we can't |
| 66 | + * easily alter the phar file */ |
| 67 | + runPhpCommand([ |
| 68 | + '-d error_reporting=0', |
| 69 | + 'wp-cli.phar', |
| 70 | + 'core', |
| 71 | + 'install', |
| 72 | + '--url=wordpress.local', |
| 73 | + '--title="Wordpress"', |
| 74 | + '--admin_user=wordpress', |
| 75 | + '--admin_password=wordpress', |
| 76 | + '--admin_email=benchmark@php.net', |
| 77 | + ], $dir); |
| 78 | + |
| 79 | + // Warmup |
| 80 | + runPhpCommand([$dir . '/index.php'], $dir); |
| 81 | + return runValgrindPhpCgiCommand([$dir . '/index.php'], cwd: $dir, jit: $jit, warmup: 50); |
| 82 | +} |
| 83 | + |
| 84 | +function runPhpCommand(array $args, ?string $cwd = null): ProcessResult { |
| 85 | + return runCommand([PHP_BINARY, ...$args], $cwd); |
| 86 | +} |
| 87 | + |
| 88 | +function runValgrindPhpCgiCommand( |
| 89 | + array $args, |
| 90 | + ?string $cwd = null, |
| 91 | + bool $jit = false, |
| 92 | + int $warmup = 0, |
| 93 | +): array { |
| 94 | + global $phpCgi; |
| 95 | + $process = runCommand([ |
| 96 | + 'valgrind', |
| 97 | + '--tool=callgrind', |
| 98 | + '--dump-instr=yes', |
| 99 | + '--callgrind-out-file=/dev/null', |
| 100 | + '--', |
| 101 | + $phpCgi, |
| 102 | + '-T' . ($warmup ? $warmup . ',' : '') . '1', |
| 103 | + '-d max_execution_time=0', |
| 104 | + '-d opcache.enable=1', |
| 105 | + '-d opcache.jit_buffer_size=' . ($jit ? '128M' : '0'), |
| 106 | + ...$args, |
| 107 | + ]); |
| 108 | + $instructions = extractInstructionsFromValgrindOutput($process->stderr); |
| 109 | + return ['instructions' => $instructions]; |
| 110 | +} |
| 111 | + |
| 112 | +function extractInstructionsFromValgrindOutput(string $output): string { |
| 113 | + preg_match("(==[0-9]+== Events : Ir\n==[0-9]+== Collected : (?<instructions>[0-9]+))", $output, $matches); |
| 114 | + return $matches['instructions'] ?? throw new \Exception('Unexpected valgrind output'); |
| 115 | +} |
| 116 | + |
| 117 | +main(); |
0 commit comments