diff options
Diffstat (limited to 'deps/v8/tools/avg.py')
-rwxr-xr-x | deps/v8/tools/avg.py | 172 |
1 files changed, 105 insertions, 67 deletions
diff --git a/deps/v8/tools/avg.py b/deps/v8/tools/avg.py index b9ceb0d907..5741acd388 100755 --- a/deps/v8/tools/avg.py +++ b/deps/v8/tools/avg.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python + # Copyright 2018 the V8 project authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can # be found in the LICENSE file. @@ -22,50 +23,53 @@ will output [10/10] [default] : avg 22,885.80 stddev 1,941.80 ( 17,584.00 - 24,266.00) Kps """ +# for py2/py3 compatibility +from __future__ import print_function + import argparse -import subprocess +import math import re -import numpy -import time -import sys import signal +import subprocess +import sys -parser = argparse.ArgumentParser( +PARSER = argparse.ArgumentParser( description="A script that averages numbers from another script's output", epilog="Example:\n\tavg.py 10 bash -c \"echo A: 100; echo B 120; sleep .1\"" ) -parser.add_argument( +PARSER.add_argument( 'repetitions', type=int, help="number of times the command should be repeated") -parser.add_argument( +PARSER.add_argument( 'command', nargs=argparse.REMAINDER, help="command to run (no quotes needed)") -parser.add_argument( +PARSER.add_argument( '--echo', '-e', action='store_true', default=False, help="set this flag to echo the command's output") -args = vars(parser.parse_args()) +ARGS = vars(PARSER.parse_args()) -if (len(args['command']) == 0): +if not ARGS['command']: print("No command provided.") exit(1) class FieldWidth: - def __init__(self, key=0, average=0, stddev=0, min=0, max=0): - self.w = dict(key=key, average=average, stddev=stddev, min=min, max=max) + def __init__(self, points=0, key=0, average=0, stddev=0, min_width=0, max_width=0): + self.widths = dict(points=points, key=key, average=average, stddev=stddev, + min=min_width, max=max_width) - def max_with(self, w2): - self.w = {k: max(v, w2.w[k]) for k, v in self.w.items()} + def max_widths(self, other): + self.widths = {k: max(v, other.widths[k]) for k, v in self.widths.items()} def __getattr__(self, key): - return self.w[key] + return self.widths[key] def fmtS(string, width=0): @@ -76,6 +80,27 @@ def fmtN(num, width=0): return "{0:>{1},.2f}".format(num, width) +def fmt(num): + return "{0:>,.2f}".format(num) + + +def format_line(points, key, average, stddev, min_value, max_value, + unit_string, widths): + return "{:>{}}; {:<{}}; {:>{}}; {:>{}}; {:>{}}; {:>{}}; {}".format( + points, widths.points, + key, widths.key, + average, widths.average, + stddev, widths.stddev, + min_value, widths.min, + max_value, widths.max, + unit_string) + + +def fmt_reps(msrmnt): + rep_string = str(ARGS['repetitions']) + return "[{0:>{1}}/{2}]".format(msrmnt.size(), len(rep_string), rep_string) + + class Measurement: def __init__(self, key, unit): @@ -102,14 +127,21 @@ class Measurement: except ValueError: print("Ignoring non-numeric value", value) - def status(self, w): - return "{}: avg {} stddev {} ({} - {}) {}".format( - fmtS(self.key, w.key), fmtN(self.average, w.average), - fmtN(self.stddev(), w.stddev), fmtN(self.min, w.min), - fmtN(self.max, w.max), fmtS(self.unit_string())) + def status(self, widths): + return "{} {}: avg {} stddev {} ({} - {}) {}".format( + fmt_reps(self), + fmtS(self.key, widths.key), fmtN(self.average, widths.average), + fmtN(self.stddev(), widths.stddev), fmtN(self.min, widths.min), + fmtN(self.max, widths.max), fmtS(self.unit_string())) + + def result(self, widths): + return format_line(self.size(), self.key, fmt(self.average), + fmt(self.stddev()), fmt(self.min), + fmt(self.max), self.unit_string(), + widths) def unit_string(self): - if self.unit == None: + if not self.unit: return "" return self.unit @@ -119,21 +151,24 @@ class Measurement: return self.M2 / (self.count - 1) def stddev(self): - return numpy.sqrt(self.variance()) + return math.sqrt(self.variance()) def size(self): return len(self.values) def widths(self): return FieldWidth( - key=len(fmtS(self.key)), - average=len(fmtN(self.average)), - stddev=len(fmtN(self.stddev())), - min=len(fmtN(self.min)), - max=len(fmtN(self.max))) + points=len("{}".format(self.size())) + 2, + key=len(self.key), + average=len(fmt(self.average)), + stddev=len(fmt(self.stddev())), + min_width=len(fmt(self.min)), + max_width=len(fmt(self.max))) -rep_string = str(args['repetitions']) +def result_header(widths): + return format_line("#/{}".format(ARGS['repetitions']), + "id", "avg", "stddev", "min", "max", "unit", widths) class Measurements: @@ -141,70 +176,73 @@ class Measurements: def __init__(self): self.all = {} self.default_key = '[default]' - self.max_widths = FieldWidth() + self.max_widths = FieldWidth( + points=len("{}".format(ARGS['repetitions'])) + 2, + key=len("id"), + average=len("avg"), + stddev=len("stddev"), + min_width=len("min"), + max_width=len("max")) + self.last_status_len = 0 def record(self, key, value, unit): - if (key == None): + if not key: key = self.default_key if key not in self.all: self.all[key] = Measurement(key, unit) self.all[key].addValue(value) - self.max_widths.max_with(self.all[key].widths()) + self.max_widths.max_widths(self.all[key].widths()) def any(self): - if len(self.all) >= 1: + if self.all: return next(iter(self.all.values())) - else: - return None + return None - def format_status(self): - m = self.any() - if m == None: - return "" - return m.status(self.max_widths) - - def format_num(self, m): - return "[{0:>{1}}/{2}]".format(m.size(), len(rep_string), rep_string) + def print_results(self): + print("{:<{}}".format("", self.last_status_len), end="\r") + print(result_header(self.max_widths), sep=" ") + for key in sorted(self.all): + print(self.all[key].result(self.max_widths), sep=" ") def print_status(self): - if len(self.all) == 0: - print("No results found. Check format?") - return - print(self.format_num(self.any()), self.format_status(), sep=" ", end="") - - def print_results(self): - for key in self.all: - m = self.all[key] - print(self.format_num(m), m.status(self.max_widths), sep=" ") + status = "No results found. Check format?" + measurement = MEASUREMENTS.any() + if measurement: + status = measurement.status(MEASUREMENTS.max_widths) + print("{:<{}}".format(status, self.last_status_len), end="\r") + self.last_status_len = len(status) -measurements = Measurements() +MEASUREMENTS = Measurements() -def signal_handler(signal, frame): +def signal_handler(signum, frame): print("", end="\r") - measurements.print_status() - print() - measurements.print_results() + MEASUREMENTS.print_results() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) -for x in range(0, args['repetitions']): - proc = subprocess.Popen(args['command'], stdout=subprocess.PIPE) +SCORE_REGEX = (r'\A((console.timeEnd: )?' + r'(?P<key>[^\s:,]+)[,:]?)?' + r'(^\s*|\s+)' + r'(?P<value>[0-9]+(.[0-9]+)?)' + r'\ ?(?P<unit>[^\d\W]\w*)?[.\s]*\Z') + +for x in range(0, ARGS['repetitions']): + proc = subprocess.Popen(ARGS['command'], stdout=subprocess.PIPE) for line in proc.stdout: - if args['echo']: + if ARGS['echo']: print(line.decode(), end="") - for m in re.finditer( - r'\A((?P<key>.*[^\s\d:]+)[:]?)?\s*(?P<value>[0-9]+(.[0-9]+)?)\ ?(?P<unit>[^\d\W]\w*)?\s*\Z', - line.decode()): - measurements.record(m.group('key'), m.group('value'), m.group('unit')) + for m in re.finditer(SCORE_REGEX, line.decode()): + MEASUREMENTS.record(m.group('key'), m.group('value'), m.group('unit')) proc.wait() if proc.returncode != 0: print("Child exited with status %d" % proc.returncode) break - measurements.print_status() - print("", end="\r") -measurements.print_results() + MEASUREMENTS.print_status() + +# Print final results +MEASUREMENTS.print_results() |