aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Rames <alexandre.rames@linaro.org>2016-02-17 09:12:55 +0000
committerAlexandre Rames <alexandre.rames@linaro.org>2016-02-17 09:12:55 +0000
commitc04e7c2075df1711cad820ffd4601c511d781b8f (patch)
treecb360f9037afc14b254114cb54850738161e9dc9
parentaa0012f9a104c2d87c77b0de8c4c6ffbfdd449f3 (diff)
downloadart-testing-c04e7c2075df1711cad820ffd4601c511d781b8f.tar.gz
Revert "Revert "Improve the JSON output of the compilation statistics tools.""
This reverts commit aa0012f9a104c2d87c77b0de8c4c6ffbfdd449f3. Change-Id: I1170a0bd2e5eaadf2b8f3178c05d7755e54d7518
-rwxr-xr-xcompare.py54
-rwxr-xr-xrun.py8
-rwxr-xr-xtest/test.py2
-rwxr-xr-xtools/benchmarks/run.py4
-rwxr-xr-xtools/compilation_statistics/compare.py107
-rwxr-xr-xtools/compilation_statistics/run.py138
-rw-r--r--tools/utils.py43
-rw-r--r--tools/utils_stats.py15
8 files changed, 136 insertions, 235 deletions
diff --git a/compare.py b/compare.py
index 9072366..4b55fcb 100755
--- a/compare.py
+++ b/compare.py
@@ -17,23 +17,52 @@
import argparse
import os
import pickle
-import sys
+
+from collections import OrderedDict
from tools import utils
from tools import utils_stats
-sys.path.insert(0, os.path.join(utils.dir_tools, 'compilation_statistics'))
-
-from compare import PrintDiff
-
def BuildOptions():
parser = argparse.ArgumentParser(
- description = "Compare two results of the associated `run.py` script.",
+ description = "Compare two result sets.",
# Print default values.
formatter_class = argparse.ArgumentDefaultsHelpFormatter)
utils.AddCommonCompareOptions(parser)
return parser.parse_args()
+def PrintDiff(data_1, data_2, key=None, indentation=''):
+ indentation_level = ' '
+ if data_1 or data_2:
+ if (isinstance(data_1, OrderedDict) or isinstance(data_1, dict) or data_1 is None) and \
+ (isinstance(data_2, OrderedDict) or isinstance(data_2, dict) or data_2 is None):
+ if key is not None:
+ print(indentation + key)
+ entries = []
+ list_1 = list(data_1.keys()) if data_1 else []
+ list_2 = list(data_2.keys()) if data_2 else []
+ for k in utils.MergeLists(list_1, list_2):
+ value_1 = data_1[k] if data_1 and k in data_1 else None
+ value_2 = data_2[k] if data_2 and k in data_2 else None
+ maybe_entry = PrintDiff(value_1, value_2, k, indentation + indentation_level)
+ if maybe_entry is not None:
+ entries.append(maybe_entry)
+ if entries:
+ utils_stats.PrintTable([''] + utils_stats.stats_diff_headers,
+ ['s'] + utils_stats.stats_diff_formats,
+ entries)
+ print('')
+ elif (isinstance(data_1, list) or data_1 is None) and \
+ (isinstance(data_2, list) or data_2 is None):
+ list_1 = data_1 if data_1 else [0.0]
+ list_2 = data_2 if data_2 else [0.0]
+ m1, M1, ave1, d1, dp1 = utils_stats.ComputeStats(list_1)
+ m2, M2, ave2, d2, dp2 = utils_stats.ComputeStats(list_2)
+ return [indentation + key] + \
+ [ave1, dp1, ave2, dp2, utils_stats.GetRelativeDiff(ave1, ave2)]
+ elif type(data_1) != type(data_2):
+ utils.Error('The data types differ between result sets.')
+
if __name__ == "__main__":
args = BuildOptions()
pkl_file_1 = open(args.res_1, 'rb')
@@ -42,15 +71,4 @@ if __name__ == "__main__":
res_2 = pickle.load(pkl_file_2)
pkl_file_1.close()
pkl_file_2.close()
- results = sorted([result for result in res_1.keys() if result in res_2])
-
- for r in results:
- if r == 'benchmarks':
- f = utils_stats.PrintDiff
- elif r == 'compilation_statistics':
- f = PrintDiff
- else:
- continue
-
- f(res_1[r], res_2[r])
- print('')
+ PrintDiff(res_1, res_2)
diff --git a/run.py b/run.py
index 40fe698..a7bdcf9 100755
--- a/run.py
+++ b/run.py
@@ -18,6 +18,8 @@ import argparse
import os
import sys
+from collections import OrderedDict
+
from tools import utils
from tools import utils_stats
from tools.benchmarks.run import GetBenchmarkStats
@@ -44,11 +46,11 @@ if __name__ == "__main__":
utils.Warning('Running this script is supported only on Linux.')
args = BuildOptions()
- result = dict()
- result['benchmarks'] = GetBenchmarkStats(args)
+ result = OrderedDict([(utils.benchmarks_label, GetBenchmarkStats(args))])
if args.target:
- result['compilation_statistics'] = GetCompilationStats(args)
+ result[utils.compilation_statistics_label] = GetCompilationStats(args)
+ utils.PrintResult(result)
utils.OutputObject(result, 'pkl', args.output_pkl)
utils.OutputObject(result, 'json', args.output_json)
diff --git a/test/test.py b/test/test.py
index 2a8a2a0..7ebbe11 100755
--- a/test/test.py
+++ b/test/test.py
@@ -153,7 +153,7 @@ def TestCompilationStatistics(target=utils.adb_default_target_string):
args.append(os.path.join(utils.dir_build, "bench.apk"))
run_py = os.path.join(utils.dir_root, "tools", "compilation_statistics", "run.py")
- compare_py = os.path.join(utils.dir_root, "tools", "compilation_statistics", "compare.py")
+ compare_py = os.path.join(utils.dir_root, "compare.py")
rc |= TestCommand(["./build.sh", "-t"], _cwd=utils.dir_root)
rc |= TestCommand([run_py, "--output-pkl=/tmp/res1"] + args, _cwd=utils.dir_root)
rc |= TestCommand([run_py, "--output-pkl=/tmp/res2"] + args, _cwd=utils.dir_root)
diff --git a/tools/benchmarks/run.py b/tools/benchmarks/run.py
index 59c1523..76c75b5 100755
--- a/tools/benchmarks/run.py
+++ b/tools/benchmarks/run.py
@@ -256,13 +256,13 @@ def GetBenchmarkStats(args):
utils.Error("The benchmarks did *not* run successfully. (rc = %d)" % rc, rc)
res = OrderedDict(sorted(result.items()))
- utils_stats.PrintStats(res, iterations = args.iterations)
- print('')
return res
if __name__ == "__main__":
args = BuildOptions()
result = GetBenchmarkStats(args)
+ utils_stats.PrintStats(result, iterations = args.iterations)
+ print('')
utils.OutputObject(result, 'pkl', args.output_pkl)
utils.OutputObject(result, 'json', args.output_json)
# Output in CSV format.
diff --git a/tools/compilation_statistics/compare.py b/tools/compilation_statistics/compare.py
deleted file mode 100755
index 48f7c57..0000000
--- a/tools/compilation_statistics/compare.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#! /usr/bin/env python3
-
-# Copyright (C) 2015 Linaro Limited. All rights received.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import argparse
-import os
-import pickle
-import sys
-
-dir_compilation_statistics = os.path.dirname(os.path.realpath(__file__))
-dir_tools = os.path.join(dir_compilation_statistics, '..')
-sys.path.insert(0, dir_tools)
-
-import utils
-import utils_stats
-from run import CompileStats, MemoryUsage, OATSize, memory_stats_fields, time_stats_fields
-
-def BuildOptions():
- parser = argparse.ArgumentParser(
- description = "Compare two results of the associated `run.py` script.",
- # Print default values.
- formatter_class = argparse.ArgumentDefaultsHelpFormatter)
- utils.AddCommonCompareOptions(parser)
- return parser.parse_args()
-
-def GetMemoryEntries(stats_1, stats_2):
- res = [['Memory usage', '', '', '']]
-
- for i in range(len(memory_stats_fields)):
- if stats_1.memory_usage[i].si_prefix == stats_2.memory_usage[i].si_prefix:
- res.append([' ' + memory_stats_fields[i] + ' (' + stats_1.memory_usage[i].si_prefix + 'B)',
- '%d' % stats_1.memory_usage[i].value, '%d' % stats_2.memory_usage[i].value,
- '%.3f' % utils_stats.GetRelativeDiff(stats_1.memory_usage[i].value,
- stats_2.memory_usage[i].value)])
-
- return res
-
-def GetSizeEntries(stats_1, stats_2):
- res = [['OAT size', '', '', ''], [' ' + 'Total (B)',
- '%d' % stats_1.oat_size.total_size,
- '%d' % stats_2.oat_size.total_size,
- '%.3f' % utils_stats.GetRelativeDiff(stats_1.oat_size.total_size,
- stats_2.oat_size.total_size)]]
-
- for s in sorted(set(stats_1.oat_size.section_sizes.keys()) | set(stats_2.oat_size.section_sizes.keys())):
- value_1 = stats_1.oat_size.section_sizes[s] if s in stats_1.oat_size.section_sizes else 0
- value_2 = stats_2.oat_size.section_sizes[s] if s in stats_2.oat_size.section_sizes else 0
- res.append([' ' * 2 + s, '%d' % value_1, '%d' % value_2,
- '%.3f' % utils_stats.GetRelativeDiff(value_1, value_2)])
-
- return res
-
-def GetTimeEntries(stats_1, stats_2):
- res = [['Compile time', '', '', '']]
- time_stats_1 = list(utils_stats.ComputeStats(stats_1.compile_times))
- time_stats_2 = list(utils_stats.ComputeStats(stats_2.compile_times))
- si_factor, si_prefix = utils.PrettySIFactor(time_stats_1[0])
-
- for i in range(len(time_stats_1)):
- field = ' ' + time_stats_fields[i]
- value_1 = time_stats_1[i]
- value_2 = time_stats_2[i]
- diff = '%.3f' % utils_stats.GetRelativeDiff(value_1, value_2)
-
- if i < len(time_stats_1) - 1:
- field += ' (' + si_prefix + 's)'
- value_1 = value_1 / si_factor
- value_2 = value_2 / si_factor
-
- res.append([field, '%.3f' % value_1, '%.3f' % value_2, diff])
-
- return res
-
-def PrintStatsDiff(apk, stats_1, stats_2):
- utils_stats.PrintTable([apk, 'Value 1', 'Value 2', '(value 2 - value 1) / value 1 * 100'],
- ['s', 's', 's', 's'],
- GetTimeEntries(stats_1, stats_2) + GetMemoryEntries(stats_1, stats_2) + \
- GetSizeEntries(stats_1, stats_2))
-
-def PrintDiff(stats_1, stats_2):
- apk_list = [apk for apk in sorted(stats_1.keys()) if apk in stats_2]
-
- for apk in apk_list:
- PrintStatsDiff(apk, stats_1[apk], stats_2[apk])
- print('')
-
-if __name__ == "__main__":
- args = BuildOptions()
- pkl_file_1 = open(args.res_1, 'rb')
- pkl_file_2 = open(args.res_2, 'rb')
- res_1 = pickle.load(pkl_file_1)
- res_2 = pickle.load(pkl_file_2)
- pkl_file_1.close()
- pkl_file_2.close()
- PrintDiff(res_1, res_2)
diff --git a/tools/compilation_statistics/run.py b/tools/compilation_statistics/run.py
index 3588e50..3ce7e4c 100755
--- a/tools/compilation_statistics/run.py
+++ b/tools/compilation_statistics/run.py
@@ -15,7 +15,6 @@
# limitations under the License.
import argparse
-import collections
import glob
import json
import os
@@ -27,6 +26,8 @@ import sys
import tempfile
import time
+from collections import OrderedDict
+
dir_compilation_statistics = os.path.dirname(os.path.realpath(__file__))
dir_tools = os.path.join(dir_compilation_statistics, '..')
sys.path.insert(0, dir_tools)
@@ -35,23 +36,22 @@ import utils
import utils_adb
import utils_stats
-CompileStats = collections.namedtuple('CompileStats', ['compile_times', 'memory_usage', 'oat_size'])
-MemoryUsage = collections.namedtuple('MemoryUsage', ['value', 'si_prefix'])
-OATSize = collections.namedtuple('OATSize', ['total_size', 'section_sizes'])
-memory_stats_fields = ['Arena', 'Java', 'Native', 'Free native']
-sections = set(['.bss', '.rodata', '.text'])
-time_stats_fields = ['Min', 'Max', 'Mean', 'Stdev', 'Stdev (% of mean)']
+memory_unit_prefixes = {'' : 1, 'G' : 2 ** 30, 'K' : 2 ** 10, 'M' : 2 ** 20}
+sections = set(['.bss', '.rodata', '.text', 'Total'])
def BuildOptions():
parser = argparse.ArgumentParser(
- description = '''Collect statistics about the APK compilation process on a target adb
- device: Compilation time, memory usage by the compiler (arena, Java,
- and native allocations, and free native memory), and size of the
- generated executable (total, .bss, .rodata, and .text section sizes).''',
+ description = '''Collect statistics about the APK compilation process on a target
+ adb device: Compilation time, memory usage by the compiler
+ (arena, Java, and native allocations, and free native memory),
+ and size of the generated executable (total, .bss, .rodata, and
+ .text section sizes).''',
# Print default values.
formatter_class = argparse.ArgumentDefaultsHelpFormatter)
- parser.add_argument('pathnames', nargs = '+', help='''Path containing APK files or a file
- name for which compilation statistics should be collected.''')
+ parser.add_argument('pathnames',
+ nargs = '+',
+ help='''Path containing APK files or a file name for which
+ compilation statistics should be collected.''')
utils.AddCommonRunOptions(parser)
utils.AddOutputFormatOptions(parser, utils.default_output_formats)
@@ -67,63 +67,24 @@ def BuildOptions():
return args
-def GetMemoryEntries(stats):
- res = [['Memory usage', '']]
-
- for i in range(len(memory_stats_fields)):
- res.append([' ' + memory_stats_fields[i] + ' (' + stats.memory_usage[i].si_prefix + 'B)',
- '%d' % stats.memory_usage[i].value])
-
- return res
-
-def GetSizeEntries(stats):
- res = [['OAT size', ''], [' ' + 'Total (B)', '%d' % stats.oat_size.total_size]]
-
- for s in sorted(stats.oat_size.section_sizes.keys()):
- res.append([' ' * 2 + s, '%d' % stats.oat_size.section_sizes[s]])
-
- return res
-
-def GetTimeEntries(stats):
- res = [['Compile time', '']]
- time_stats = list(utils_stats.ComputeStats(stats.compile_times))
- si_factor, si_prefix = utils.PrettySIFactor(time_stats[0])
-
- for i in range(len(time_stats)):
- field = ' ' + time_stats_fields[i]
- value = time_stats[i]
-
- if i < len(time_stats_fields) - 1:
- field += ' (' + si_prefix + 's)'
- value = value / si_factor
-
- res.append([field, '%.3f' % value])
-
- return res
-
-def PrintStatsTable(apk, stats):
- utils_stats.PrintTable([apk, ''], ['s', 's'], GetTimeEntries(stats) + GetMemoryEntries(stats) + \
- GetSizeEntries(stats))
-
def GetStats(apk,
target,
isa,
compiler_mode,
target_copy_path,
iterations,
- alloc_parser,
- size_parser,
work_dir):
apk_path = os.path.join(target_copy_path, apk)
oat = apk_path + '.oat'
- # Only the output of the first command is necessary; execute in a subshell to guarantee PID value;
- # only one thread is used for compilation to reduce measurement noise.
+ # Only the output of the first command is necessary; execute in a subshell
+ # to guarantee PID value; only one thread is used for compilation to reduce
+ # measurement noise.
dex2oat_options = utils.GetDex2oatOptions(compiler_mode)
command = '(echo $BASHPID && exec dex2oat -j1 ' + \
' '.join(dex2oat_options) + \
' --dex-file=' + apk_path + ' --oat-file=' + oat
command += ' --instruction-set=' + isa + ') | head -n1'
- compile_times = []
+ compilation_times = []
for i in range(iterations):
rc, out = utils_adb.shell(command, target)
@@ -131,36 +92,30 @@ def GetStats(apk,
stats_command = 'logcat -dsv process dex2oat | grep "^I([[:space:]]*' + \
out.rstrip() + ').*took" | tail -n1'
rc, out = utils_adb.shell(stats_command, target)
- alloc_stats = alloc_parser.match(out)
+ compile_time = re.match('.*?took (?P<value>.*?)(?P<unit>[mnu]{,1})s.*?\)', out)
- if not alloc_stats:
+ if not compile_time:
utils.Error('dex2oat failed; check adb logcat.')
- compile_times.append(utils.GetTimeValue(float(alloc_stats.group(1)), alloc_stats.group(2)))
-
- # The rest of the statistics are deterministic, so there is no need to run several iterations;
- # just get the values from the last run.
- memory_usage = []
-
- for i in range(4):
- memory_usage.append(MemoryUsage(int(alloc_stats.group(2 * i + 3)), alloc_stats.group(2 * i + 4)))
+ value = float(compile_time.group('value')) * \
+ utils.si_unit_prefixes[compile_time.group('unit')]
+ compilation_times.append(value)
+ # The rest of the statistics are deterministic, so there is no need to run several
+ # iterations; just get the values from the last run.
+ out = out[compile_time.end():]
+ memory_stats = OrderedDict((m[0], [int(m[1]) * memory_unit_prefixes[m[2]]]) for m
+ in re.findall(' (.*?)=([0-9]+)([GKM]{,1})B', out))
local_oat = os.path.join(utils.dir_root, work_dir, apk + '.oat')
utils_adb.pull(oat, local_oat, target)
command = ['size', '-A', '-d', local_oat]
rc, outerr = utils.Command(command)
- section_sizes = dict()
- total_size = 0
-
- for s in size_parser.findall(outerr):
- value = int(s[1])
-
- if s[0] in sections:
- section_sizes[s[0]] = value
- elif s[0] == 'Total':
- total_size = value
-
- return [(apk, CompileStats(compile_times, memory_usage, OATSize(total_size, section_sizes)))]
+ section_sizes = OrderedDict((s[0], [int(s[1])]) for s
+ in re.findall('(\S+)\s+([0-9]+).*', outerr)
+ if s[0] in sections)
+ return OrderedDict([(utils.compilation_times_label, compilation_times),
+ (utils.memory_stats_label, memory_stats),
+ (utils.oat_size_label, section_sizes)])
def GetISA(target, mode):
if not mode:
@@ -194,12 +149,8 @@ def GetISA(target, mode):
def GetCompilationStats(args):
utils.CheckDependencies(['adb', 'size'])
- alloc_parser = re.compile('.*?took (.*?)([mnu]{,1})s.*?=([0-9]+)([GKM]{,1})B' \
- '.*?=([0-9]+)([GKM]{,1})B.*?=([0-9]+)([GKM]{,1})B' \
- '.*?=([0-9]+)([GKM]{,1})B')
- size_parser = re.compile('(\S+)\s+([0-9]+).*')
isa = GetISA(args.target, args.mode)
- res = dict()
+ res = OrderedDict()
work_dir = tempfile.mkdtemp()
apk_list = []
@@ -207,22 +158,18 @@ def GetCompilationStats(args):
if os.path.isfile(pathname):
apk_list.append(pathname)
else:
- apk_list[len(apk_list):] = [dentry for dentry in glob.glob(os.path.join(pathname, '*.apk'))
- if os.path.isfile(dentry)]
+ dentries = [dentry for dentry in glob.glob(os.path.join(pathname, '*.apk'))
+ if os.path.isfile(dentry)]
+ apk_list[len(apk_list):] = dentries
- for apk in apk_list:
+ for apk in sorted(apk_list):
utils_adb.push(apk, args.target_copy_path, args.target)
- res.update(GetStats(os.path.basename(apk), args.target, isa,
- args.compiler_mode, args.target_copy_path,
- args.iterations, alloc_parser, size_parser, work_dir))
+ apk_name = os.path.basename(apk)
+ res[apk_name] = GetStats(apk_name, args.target, isa,
+ args.compiler_mode, args.target_copy_path,
+ args.iterations, work_dir)
shutil.rmtree(work_dir)
- apk_list = sorted(res)
-
- for apk in apk_list:
- PrintStatsTable(apk, res[apk])
- print('')
-
return res
if __name__ == "__main__":
@@ -232,5 +179,6 @@ if __name__ == "__main__":
args = BuildOptions()
stats = GetCompilationStats(args)
+ utils.PrintResult(stats)
utils.OutputObject(stats, 'pkl', args.output_pkl)
utils.OutputObject(stats, 'json', args.output_json)
diff --git a/tools/utils.py b/tools/utils.py
index 39daa7e..f248ac2 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -23,8 +23,14 @@ import sys
import time
import traceback
+from collections import OrderedDict
dir_tools = os.path.dirname(os.path.realpath(__file__))
+sys.path.insert(0, dir_tools)
+
+import utils_stats
+
+
dir_root = os.path.realpath(os.path.join(dir_tools, '..'))
dir_benchmarks = os.path.join(dir_root, 'benchmarks')
dir_out = os.path.join(dir_root, 'out')
@@ -34,7 +40,12 @@ dir_framework = os.path.join(dir_root, 'framework')
# Constant shared values that should not be modified.
-si_factors = {'m' : 0.001, 'n' : 0.000000001, 'u' : 0.000001}
+si_unit_prefixes = {'' : 1, 'G' : 10 ** 9, 'K' : 10 ** 3, 'M' : 10 ** 6, 'm' : 10 ** -3, 'n' : 10 ** -9, 'u' : 10 ** -6}
+benchmarks_label = 'benchmarks'
+compilation_statistics_label = 'compilation statistics'
+compilation_times_label = 'compilation times'
+memory_stats_label = 'memory statistics'
+oat_size_label = 'oat size'
adb_default_target_string = '<default>'
adb_default_target_copy_path = '/data/local/tmp'
default_mode = ''
@@ -84,18 +95,24 @@ def ensure_dir(path):
except:
Error('Failed to ensure the directory `%s` exists.' % path)
-def GetTimeValue(value, si_prefix):
- return value * si_factors[si_prefix] if si_prefix else value
+def MergeLists(x, y):
+ # To simplify things, assume that either y is the same as x, or it contains
+ # elements that are ordered after those in x.
+ # TODO: Use topological sorting or a more efficient algorithm.
+ return x + [e for e in y if e not in x]
def PrettySIFactor(value):
si_factor = float('inf')
si_prefix = ''
- for i in si_factors.items():
+ for i in si_unit_prefixes.items():
if i[1] < si_factor and value < i[1] * 1000:
si_factor = i[1]
si_prefix = i[0]
+ if si_factor == float('inf'):
+ si_factor = 1
+
return si_factor, si_prefix
def NameMatchesAnyFilter(name, filters):
@@ -226,3 +243,21 @@ def CheckDependencies(dependencies):
if rc:
Error("Couldn't find `" + d + "`.")
+
+def PrintResult(data, key=None, indentation=''):
+ indentation_level = ' '
+ if isinstance(data, OrderedDict) or isinstance(data, dict):
+ if key is not None:
+ print(indentation + key)
+ entries = []
+ for k in data:
+ maybe_entry = PrintResult(data[k], k, indentation + indentation_level)
+ if maybe_entry is not None:
+ entries.append(maybe_entry)
+ if entries:
+ utils_stats.PrintTable([''] + utils_stats.stats_headers,
+ ['s'] + utils_stats.stats_formats,
+ entries)
+ print('')
+ elif isinstance(data, list):
+ return [indentation + key] + list(utils_stats.ComputeStats(data))
diff --git a/tools/utils_stats.py b/tools/utils_stats.py
index ae91c6c..a3aa168 100644
--- a/tools/utils_stats.py
+++ b/tools/utils_stats.py
@@ -18,6 +18,12 @@ import math
from functools import reduce
+stats_diff_headers = ['mean1', 'stdev1 (% of mean1)', 'mean2',
+ 'stdev2 (% of mean2)', '(mean2 - mean1) / mean1 * 100']
+stats_diff_formats = ['.3f', '.3f', '.3f', '.3f', '.3f']
+stats_headers = ['min', 'max', 'mean', 'stdev', 'stdev (% of mean)']
+stats_formats = ['.3f', '.3f', '.3f', '.3f', '.3f']
+
def CalcGeomean(nums):
assert len(nums) != 0
return math.exp((sum(map(lambda x: math.log(x), nums))) / len(nums))
@@ -51,7 +57,7 @@ def GetSuiteName(benchmark):
return benchmark.split("/", 2)[1]
def PrintStats(dict_results, iterations = None):
- headers = ['', 'min', 'max', 'mean', 'stdev', 'stdev (% of mean)']
+ headers = [''] + stats_headers
results = []
stats_dict = {}
@@ -67,7 +73,7 @@ def PrintStats(dict_results, iterations = None):
results.append([benchmark] + list(data))
- PrintTable(headers, ['.3f'] * len(headers), results)
+ PrintTable(headers, ['.3f'] + stats_formats, results)
# overall and per suite geomeans calculations
print("\nGEOMEANS:")
@@ -105,8 +111,7 @@ def PrintDiff(res_1, res_2, title = ''):
# Only print results for benchmarks present in both sets of results.
# Pay attention to maintain the order of the keys.
benchmarks = [b for b in res_1.keys() if b in res_2.keys()]
- headers = [title, 'mean1', 'stdev1 (% of mean1)', 'mean2', 'stdev2 (% of mean2)',
- '(mean2 - mean1) / mean1 * 100']
+ headers = [title] + stats_diff_headers
results = []
stats_dict = {}
# collecting data
@@ -125,7 +130,7 @@ def PrintDiff(res_1, res_2, title = ''):
diff = GetRelativeDiff(ave1, ave2)
results.append([bench, ave1, dp1, ave2, dp2, diff])
- PrintTable(headers, ['.3f'] * len(headers), results)
+ PrintTable(headers, ['.3f'] + stats_diff_formats, results)
# overall and per suite geomeans calculations
print("\nGEOMEANS:")