# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Works with python2.6
import json
import math
import os
import sys
from operator
import itemgetter
from subprocess
import PIPE, Popen
class Test:
def __init__(self, path, name):
self.path = path
self.name = name
@classmethod
def from_file(cls, path, name, options):
return cls(path, name)
def find_tests(dir, substring=
None):
ans = []
for dirpath, dirnames, filenames
in os.walk(dir):
if dirpath ==
".":
continue
for filename
in filenames:
if not filename.endswith(
".js"):
continue
test = os.path.join(dirpath, filename)
if substring
is None or substring
in os.path.relpath(test, dir):
ans.append([test, filename])
return ans
def get_test_cmd(path):
return [JS,
"-f", path]
def avg(seq):
return sum(seq) / len(seq)
def stddev(seq, mean):
diffs = ((float(item) - mean) ** 2
for item
in seq)
return math.sqrt(sum(diffs) / len(seq))
def run_test(test):
env = os.environ.copy()
env[
"MOZ_GCTIMER"] =
"stderr"
cmd = get_test_cmd(test.path)
total = []
mark = []
sweep = []
close_fds = sys.platform !=
"win32"
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=close_fds, env=env)
out, err = p.communicate()
out, err = out.decode(), err.decode()
float_array = [float(_)
for _
in err.split()]
if len(float_array) == 0:
print(
"Error: No data from application. Configured with --enable-gctimer?")
sys.exit(1)
for i, currItem
in enumerate(float_array):
if i % 3 == 0:
total.append(currItem)
else:
if i % 3 == 1:
mark.append(currItem)
else:
sweep.append(currItem)
return max(total), avg(total), max(mark), avg(mark), max(sweep), avg(sweep)
def run_tests(tests, test_dir):
bench_map = {}
try:
for i, test
in enumerate(tests):
filename_str =
'"%s"' % test.name
TMax, TAvg, MMax, MAvg, SMax, SAvg = run_test(test)
bench_map[test.name] = [TMax, TAvg, MMax, MAvg, SMax, SAvg]
fmt =
'%20s: {"TMax": %4.1f, "TAvg": %4.1f, "MMax": %4.1f, "MAvg": %4.1f, "SMax": %4.1f, "SAvg": %4.1f}' # NOQA: E501
if i != len(tests) - 1:
fmt +=
","
print(fmt % (filename_str, TMax, TAvg, MMax, MAvg, SMax, MAvg))
except KeyboardInterrupt:
print(
"fail")
return dict(
(
filename,
dict(TMax=TMax, TAvg=TAvg, MMax=MMax, MAvg=MAvg, SMax=SMax, SAvg=SAvg),
)
for filename, (TMax, TAvg, MMax, MAvg, SMax, SAvg)
in bench_map.iteritems()
)
def compare(current, baseline):
percent_speedups = []
for key, current_result
in current.iteritems():
try:
baseline_result = baseline[key]
except KeyError:
print(key,
"missing from baseline")
continue
val_getter = itemgetter(
"TMax",
"TAvg",
"MMax",
"MAvg",
"SMax",
"SAvg")
BTMax, BTAvg, BMMax, BMAvg, BSMax, BSAvg = val_getter(baseline_result)
CTMax, CTAvg, CMMax, CMAvg, CSMax, CSAvg = val_getter(current_result)
if CTAvg <= BTAvg:
speedup = (CTAvg / BTAvg - 1) * 100
result =
"faster: %6.2f < baseline %6.2f (%+6.2f%%)" % (
CTAvg,
BTAvg,
speedup,
)
percent_speedups.append(speedup)
else:
slowdown = (CTAvg / BTAvg - 1) * 100
result =
"SLOWER: %6.2f > baseline %6.2f (%+6.2f%%) " % (
CTAvg,
BTAvg,
slowdown,
)
percent_speedups.append(slowdown)
print(
"%30s: %s" % (key, result))
if percent_speedups:
print(
"Average speedup: %.2f%%" % avg(percent_speedups))
if __name__ ==
"__main__":
script_path = os.path.abspath(__file__)
script_dir = os.path.dirname(script_path)
test_dir = os.path.join(script_dir,
"tests")
from optparse
import OptionParser
op = OptionParser(usage=
"%prog [options] JS_SHELL [TESTS]")
op.add_option(
"-b",
"--baseline",
metavar=
"JSON_PATH",
dest=
"baseline_path",
help=
"json file with baseline values to " "compare against",
)
(OPTIONS, args) = op.parse_args()
if len(args) < 1:
op.error(
"missing JS_SHELL argument")
# We need to make sure we are using backslashes on Windows.
JS, test_args = os.path.normpath(args[0]), args[1:]
test_list = []
bench_map = {}
test_list = find_tests(test_dir)
if not test_list:
print >> sys.stderr,
"No tests found matching command line arguments."
sys.exit(0)
test_list = [Test.from_file(tst, name, OPTIONS)
for tst, name
in test_list]
try:
print(
"{")
bench_map = run_tests(test_list, test_dir)
print(
"}")
except OSError:
if not os.path.exists(JS):
print >> sys.stderr,
"JS shell argument: file does not exist: '%s'" % JS
sys.exit(1)
else:
raise
if OPTIONS.baseline_path:
baseline_map = []
fh = open(OPTIONS.baseline_path,
"r")
baseline_map = json.load(fh)
fh.close()
compare(current=bench_map, baseline=baseline_map)