@@ -63,7 +63,8 @@ function runSymfonyDemo(bool $jit): array {
63
63
cloneRepo ($ dir , 'https://github.com/php/benchmarking-symfony-demo-2.2.3.git ' );
64
64
runPhpCommand ([$ dir . '/bin/console ' , 'cache:clear ' ]);
65
65
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 );
67
68
}
68
69
69
70
function runWordpress (bool $ jit ): array {
@@ -86,7 +87,8 @@ function runWordpress(bool $jit): array {
86
87
87
88
// Warmup
88
89
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 );
90
92
}
91
93
92
94
function runPhpCommand (array $ args , ?string $ cwd = null ): ProcessResult {
@@ -98,45 +100,86 @@ function runValgrindPhpCgiCommand(
98
100
array $ args ,
99
101
?string $ cwd = null ,
100
102
bool $ jit = false ,
101
- int $ warmup = 0 ,
102
103
int $ repeat = 1 ,
103
104
): array {
104
105
global $ phpCgi ;
105
106
106
- $ profileOut = __DIR__ . "/profiles/callgrind.out. $ name " ;
107
+ $ profileOut = __DIR__ . "/profiles/callgrind. $ name " ;
107
108
if ($ jit ) {
108
- $ profileOut .= '. jit ' ;
109
+ $ profileOut .= '- jit ' ;
109
110
}
110
111
111
112
$ process = runCommand ([
112
113
'valgrind ' ,
113
114
'--tool=callgrind ' ,
114
115
'--dump-instr=yes ' ,
116
+ '--collect-jumps=yes ' ,
115
117
"--callgrind-out-file= $ profileOut " ,
118
+ '--verbose=yes ' ,
116
119
'-- ' ,
117
120
$ phpCgi ,
118
- '-T ' . ( $ warmup ? $ warmup . ' , ' : '' ) . $ repeat ,
121
+ '-T ' . $ repeat ,
119
122
'-d max_execution_time=0 ' ,
120
123
'-d opcache.enable=1 ' ,
121
124
'-d opcache.jit= ' . ($ jit ? 'tracing ' : 'disable ' ),
122
125
'-d opcache.jit_buffer_size=128M ' ,
123
126
'-d opcache.validate_timestamps=0 ' ,
124
127
...$ args ,
125
128
]);
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
+ }
130
148
}
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 ' ]];
132
175
}
133
176
134
177
/**
135
178
* @return array<non-empty-string, numeric-string>
136
179
*/
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 ' );
140
183
}
141
184
142
185
return array_combine (explode (' ' , ltrim ($ matches [1 ], ' ' )), explode (' ' , ltrim ($ matches [2 ], ' ' )));
0 commit comments