OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 the V8 project authors. All rights reserved. | 2 # Copyright 2014 the V8 project authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """ | 6 """ |
7 Performance runner for d8. | 7 Performance runner for d8. |
8 | 8 |
9 Call e.g. with tools/run-benchmarks.py --arch ia32 some_suite.json | 9 Call e.g. with tools/run-benchmarks.py --arch ia32 some_suite.json |
10 | 10 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 "android_ia32", | 106 "android_ia32", |
107 "arm", | 107 "arm", |
108 "ia32", | 108 "ia32", |
109 "mips", | 109 "mips", |
110 "mipsel", | 110 "mipsel", |
111 "nacl_ia32", | 111 "nacl_ia32", |
112 "nacl_x64", | 112 "nacl_x64", |
113 "x64", | 113 "x64", |
114 "arm64"] | 114 "arm64"] |
115 | 115 |
116 GENERIC_RESULTS_RE = re.compile( | |
117 r"^Trace\(([^\)]+)\), Result\(([^\)]+)\), StdDev\(([^\)]+)\)$") | |
116 | 118 |
117 class Results(object): | 119 class Results(object): |
118 """Place holder for result traces.""" | 120 """Place holder for result traces.""" |
119 def __init__(self, traces=None, errors=None): | 121 def __init__(self, traces=None, errors=None): |
120 self.traces = traces or [] | 122 self.traces = traces or [] |
121 self.errors = errors or [] | 123 self.errors = errors or [] |
122 | 124 |
123 def ToDict(self): | 125 def ToDict(self): |
124 return {"traces": self.traces, "errors": self.errors} | 126 return {"traces": self.traces, "errors": self.errors} |
125 | 127 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
242 "results": self.results, | 244 "results": self.results, |
243 "stddev": self.stddev, | 245 "stddev": self.stddev, |
244 }], self.errors) | 246 }], self.errors) |
245 | 247 |
246 | 248 |
247 class Runnable(Graph): | 249 class Runnable(Graph): |
248 """Represents a runnable benchmark suite definition (i.e. has a main file). | 250 """Represents a runnable benchmark suite definition (i.e. has a main file). |
249 """ | 251 """ |
250 @property | 252 @property |
251 def main(self): | 253 def main(self): |
252 return self._suite["main"] | 254 return self._suite.get("main", "") |
253 | 255 |
254 def ChangeCWD(self, suite_path): | 256 def ChangeCWD(self, suite_path): |
255 """Changes the cwd to to path defined in the current graph. | 257 """Changes the cwd to to path defined in the current graph. |
256 | 258 |
257 The benchmarks are supposed to be relative to the suite configuration. | 259 The benchmarks are supposed to be relative to the suite configuration. |
258 """ | 260 """ |
259 suite_dir = os.path.abspath(os.path.dirname(suite_path)) | 261 suite_dir = os.path.abspath(os.path.dirname(suite_path)) |
260 bench_dir = os.path.normpath(os.path.join(*self.path)) | 262 bench_dir = os.path.normpath(os.path.join(*self.path)) |
261 os.chdir(os.path.join(suite_dir, bench_dir)) | 263 os.chdir(os.path.join(suite_dir, bench_dir)) |
262 | 264 |
(...skipping 19 matching lines...) Expand all Loading... | |
282 def __init__(self, suite, parent, arch): | 284 def __init__(self, suite, parent, arch): |
283 super(RunnableTrace, self).__init__(suite, parent, arch) | 285 super(RunnableTrace, self).__init__(suite, parent, arch) |
284 | 286 |
285 def Run(self, runner): | 287 def Run(self, runner): |
286 """Iterates over several runs and handles the output.""" | 288 """Iterates over several runs and handles the output.""" |
287 for stdout in runner(): | 289 for stdout in runner(): |
288 self.ConsumeOutput(stdout) | 290 self.ConsumeOutput(stdout) |
289 return self.GetResults() | 291 return self.GetResults() |
290 | 292 |
291 | 293 |
294 class RunnableGeneric(Runnable): | |
295 """Represents a runnable benchmark suite definition with generic traces.""" | |
296 def __init__(self, suite, parent, arch): | |
297 super(RunnableGeneric, self).__init__(suite, parent, arch) | |
298 | |
299 def Run(self, runner): | |
300 """Iterates over several runs and handles the output.""" | |
301 traces = {} | |
302 for stdout in runner(): | |
303 for line in stdout.strip().splitlines(): | |
304 match = GENERIC_RESULTS_RE.match(line) | |
305 if match: | |
306 trace = match.group(1) | |
307 result = match.group(2) | |
308 stddev = match.group(3) | |
309 trace_result = traces.setdefault(trace, Results([{ | |
310 "graphs": self.graphs + [trace], | |
311 "units": self.units, | |
312 "results": [], | |
313 "stddev": "", | |
314 }], [])) | |
315 trace_result.traces[0]["results"].append(result) | |
316 trace_result.traces[0]["stddev"] = stddev | |
Michael Achenbach
2014/08/22 14:41:26
Note: Having multiple reruns by the driver and a s
| |
317 | |
318 return reduce(lambda r, t: r + t, traces.itervalues(), Results()) | |
319 | |
320 | |
292 def MakeGraph(suite, arch, parent): | 321 def MakeGraph(suite, arch, parent): |
293 """Factory method for making graph objects.""" | 322 """Factory method for making graph objects.""" |
294 if isinstance(parent, Runnable): | 323 if isinstance(parent, Runnable): |
295 # Below a runnable can only be traces. | 324 # Below a runnable can only be traces. |
296 return Trace(suite, parent, arch) | 325 return Trace(suite, parent, arch) |
297 elif suite.get("main"): | 326 elif suite.get("main"): |
298 # A main file makes this graph runnable. | 327 # A main file makes this graph runnable. |
299 if suite.get("benchmarks"): | 328 if suite.get("benchmarks"): |
300 # This graph has subbenchmarks (traces). | 329 # This graph has subbenchmarks (traces). |
301 return Runnable(suite, parent, arch) | 330 return Runnable(suite, parent, arch) |
302 else: | 331 else: |
303 # This graph has no subbenchmarks, it's a leaf. | 332 # This graph has no subbenchmarks, it's a leaf. |
304 return RunnableTrace(suite, parent, arch) | 333 return RunnableTrace(suite, parent, arch) |
334 elif suite.get("generic"): | |
335 # This is a generic suite definition. It is either a runnable executable | |
336 # or has a main js file. | |
337 return RunnableGeneric(suite, parent, arch) | |
305 elif suite.get("benchmarks"): | 338 elif suite.get("benchmarks"): |
306 # This is neither a leaf nor a runnable. | 339 # This is neither a leaf nor a runnable. |
307 return Graph(suite, parent, arch) | 340 return Graph(suite, parent, arch) |
308 else: # pragma: no cover | 341 else: # pragma: no cover |
309 raise Exception("Invalid benchmark suite configuration.") | 342 raise Exception("Invalid benchmark suite configuration.") |
310 | 343 |
311 | 344 |
312 def BuildGraphs(suite, arch, parent=None): | 345 def BuildGraphs(suite, arch, parent=None): |
313 """Builds a tree structure of graph objects that corresponds to the suite | 346 """Builds a tree structure of graph objects that corresponds to the suite |
314 configuration. | 347 configuration. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
412 | 445 |
413 if options.json_test_results: | 446 if options.json_test_results: |
414 results.WriteToFile(options.json_test_results) | 447 results.WriteToFile(options.json_test_results) |
415 else: # pragma: no cover | 448 else: # pragma: no cover |
416 print results | 449 print results |
417 | 450 |
418 return min(1, len(results.errors)) | 451 return min(1, len(results.errors)) |
419 | 452 |
420 if __name__ == "__main__": # pragma: no cover | 453 if __name__ == "__main__": # pragma: no cover |
421 sys.exit(Main(sys.argv[1:])) | 454 sys.exit(Main(sys.argv[1:])) |
OLD | NEW |