Skip to content

Commit 3453112

Browse files
committed
measure startup, each bench run and shutdown separately
1 parent 76b989c commit 3453112

File tree

2 files changed

+70
-32
lines changed

2 files changed

+70
-32
lines changed

benchmark/benchmark.php

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ function runSymfonyDemo(bool $jit): array {
6363
cloneRepo($dir, 'https://github.com/php/benchmarking-symfony-demo-2.2.3.git');
6464
runPhpCommand([$dir . '/bin/console', 'cache:clear']);
6565
runPhpCommand([$dir . '/bin/console', 'cache:warmup']);
66-
return runValgrindPhpCgiCommand('symfony-demo', [$dir . '/public/index.php'], cwd: $dir, jit: $jit, warmup: 50, repeat: 50);
66+
67+
return runValgrindPhpCgiCommand('symfony-demo', [$dir . '/public/index.php'], cwd: $dir, jit: $jit, repeat: 100);
6768
}
6869

6970
function runWordpress(bool $jit): array {
@@ -86,7 +87,8 @@ function runWordpress(bool $jit): array {
8687

8788
// Warmup
8889
runPhpCommand([$dir . '/index.php'], $dir);
89-
return runValgrindPhpCgiCommand('wordpress', [$dir . '/index.php'], cwd: $dir, jit: $jit, warmup: 50, repeat: 50);
90+
91+
return runValgrindPhpCgiCommand('wordpress', [$dir . '/index.php'], cwd: $dir, jit: $jit, repeat: 100);
9092
}
9193

9294
function runPhpCommand(array $args, ?string $cwd = null): ProcessResult {
@@ -98,45 +100,86 @@ function runValgrindPhpCgiCommand(
98100
array $args,
99101
?string $cwd = null,
100102
bool $jit = false,
101-
int $warmup = 0,
102103
int $repeat = 1,
103104
): array {
104105
global $phpCgi;
105106

106-
$profileOut = __DIR__ . "/profiles/callgrind.out.$name";
107+
$profileOut = __DIR__ . "/profiles/callgrind.$name";
107108
if ($jit) {
108-
$profileOut .= '.jit';
109+
$profileOut .= '-jit';
109110
}
110111

111112
$process = runCommand([
112113
'valgrind',
113114
'--tool=callgrind',
114115
'--dump-instr=yes',
116+
'--collect-jumps=yes',
115117
"--callgrind-out-file=$profileOut",
118+
'--verbose',
116119
'--',
117120
$phpCgi,
118-
'-T' . ($warmup ? $warmup . ',' : '') . $repeat,
121+
'-T' . $repeat,
119122
'-d max_execution_time=0',
120123
'-d opcache.enable=1',
121124
'-d opcache.jit=' . ($jit ? 'tracing' : 'disable'),
122125
'-d opcache.jit_buffer_size=128M',
123126
'-d opcache.validate_timestamps=0',
124127
...$args,
125128
]);
126-
$valgrindMetrics = extractMetricsFromValgrindOutput($process->stderr);
127-
$instructions = $valgrindMetrics['Ir'];
128-
if ($repeat > 1) {
129-
$instructions = gmp_strval(gmp_div_q($instructions, $repeat));
129+
130+
// collect metrics for startup, each benchmark run and shutdown
131+
$metricsArr = [];
132+
foreach (['startup' => 1, ...range(2, $repeat + 1), 'shutdown' => ''] as $k => $kCallgrindOut) {
133+
$profileOutSpecific = $profileOut . '.' . $k;
134+
rename($profileOut . ($kCallgrindOut === '' ? '' : '.' . $kCallgrindOut), $profileOutSpecific);
135+
136+
$metricsArr[$k] = extractMetricsFromCallgrindFile($profileOutSpecific);
137+
}
138+
139+
// print all collected metrics
140+
print_r($metricsArr);
141+
142+
// find the fastest benchmark run
143+
$bestRunIndex = 0;
144+
foreach (range(0, $repeat - 1) as $k) {
145+
if ($metricsArr[$k]['Ir'] < $metricsArr[$bestRunIndex]['Ir']) {
146+
$bestRunIndex = $k;
147+
}
130148
}
131-
return ['instructions' => $instructions];
149+
150+
// remove non-fastest profiles from artifacts
151+
foreach (range(0, $repeat - 1) as $k) {
152+
$profileOutSpecific = $profileOut . '.' . $k;
153+
154+
if ($k !== $bestRunIndex) {
155+
unlink($profileOutSpecific);
156+
}
157+
}
158+
159+
// annotate profiles for artifacts
160+
foreach (['startup', $bestRunIndex, 'shutdown'] as $k) {
161+
$profileOutSpecific = $profileOut . '.' . $k;
162+
163+
runCommand([
164+
'callgrind_annotate',
165+
'--threshold=100',
166+
'--auto=yes',
167+
'--show-percs=no',
168+
$profileOutSpecific,
169+
new UnescapedArg('>'),
170+
"$profileOutSpecific.txt",
171+
]);
172+
}
173+
174+
return ['instructions' => $metricsArr[$bestRunIndex]['Ir']];
132175
}
133176

134177
/**
135178
* @return array<non-empty-string, numeric-string>
136179
*/
137-
function extractMetricsFromValgrindOutput(string $output): array {
138-
if (!preg_match('/==\d+== Events *:((?: +\w+)+)\n==\d+== Collected :((?: +\d+)+)\n/', $output, $matches)) {
139-
throw new \Exception('Unexpected valgrind output: ' . $output);
180+
function extractMetricsFromCallgrindFile(string $path): array {
181+
if (!preg_match('/\nevents:((?: +\w+)+)\nsummary:((?: +\d+)+)\n/', file_get_contents($path, length: 10_000), $matches)) {
182+
throw new \Exception('Unexpected callgrind data');
140183
}
141184

142185
return array_combine(explode(' ', ltrim($matches[1], ' ')), explode(' ', ltrim($matches[2], ' ')));

sapi/cgi/cgi_main.c

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,13 +2216,6 @@ consult the installation file that came with this distribution, or visit \n\
22162216
if (comma) {
22172217
warmup_repeats = atoi(php_optarg);
22182218
repeats = atoi(comma + 1);
2219-
#ifdef HAVE_VALGRIND
2220-
if (warmup_repeats > 0) {
2221-
CALLGRIND_STOP_INSTRUMENTATION;
2222-
/* We're not interested in measuring startup */
2223-
CALLGRIND_ZERO_STATS;
2224-
}
2225-
#endif
22262219
} else {
22272220
repeats = atoi(php_optarg);
22282221
}
@@ -2264,6 +2257,13 @@ consult the installation file that came with this distribution, or visit \n\
22642257
}
22652258
#endif
22662259
while (!fastcgi || fcgi_accept_request(request) >= 0) {
2260+
#ifdef HAVE_VALGRIND
2261+
if (benchmark) {
2262+
/* measure startup and each benchmark run separately */
2263+
CALLGRIND_DUMP_STATS;
2264+
}
2265+
#endif
2266+
22672267
SG(server_context) = fastcgi ? (void *)request : (void *) 1;
22682268
init_request_info(request);
22692269

@@ -2430,12 +2430,6 @@ consult the installation file that came with this distribution, or visit \n\
24302430
}
24312431
} /* end !cgi && !fastcgi */
24322432

2433-
#ifdef HAVE_VALGRIND
2434-
if (warmup_repeats == 0) {
2435-
CALLGRIND_START_INSTRUMENTATION;
2436-
}
2437-
#endif
2438-
24392433
/* request startup only after we've done all we can to
24402434
* get path_translated */
24412435
if (php_request_startup() == FAILURE) {
@@ -2554,11 +2548,6 @@ consult the installation file that came with this distribution, or visit \n\
25542548
SG(request_info).query_string = NULL;
25552549
}
25562550

2557-
#ifdef HAVE_VALGRIND
2558-
/* We're not interested in measuring shutdown */
2559-
CALLGRIND_STOP_INSTRUMENTATION;
2560-
#endif
2561-
25622551
if (!fastcgi) {
25632552
if (benchmark) {
25642553
if (warmup_repeats) {
@@ -2586,6 +2575,12 @@ consult the installation file that came with this distribution, or visit \n\
25862575
script_file = NULL;
25872576
goto do_repeat;
25882577
}
2578+
2579+
#ifdef HAVE_VALGRIND
2580+
/* measure shutdown separately */
2581+
CALLGRIND_DUMP_STATS;
2582+
#endif
2583+
25892584
break;
25902585
}
25912586

0 commit comments

Comments
 (0)