cleaned up algorithm codes and added 25th percentile for representation.
git-svn-id: http://skia.googlecode.com/svn/trunk@5139 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/bench_graph_svg.py b/bench/bench_graph_svg.py
index 78a0366..517e691 100644
--- a/bench/bench_graph_svg.py
+++ b/bench/bench_graph_svg.py
@@ -28,8 +28,8 @@
print '-r <revision>[:<revision>] the revisions to show.'
print ' Negative <revision> is taken as offset from most recent revision.'
print '-s <setting>[=<value>] a setting to show (alpha, scalar, etc).'
- print '-m <representative> use "avg", "min", or "med" for bench value.'
- print ' They correspond to average, minimum and median of bench iters.'
+ print '-m <representation> representation of bench value.'
+ print ' See _ListAlgorithm class in bench_util.py.'
print '-t <time> the time to show (w, c, g, etc).'
print '-x <int> the desired width of the svg.'
print '-y <int> the desired height of the svg.'
@@ -281,7 +281,7 @@
config_of_interest = None
bench_of_interest = None
time_of_interest = None
- rep = "avg" # bench representative calculation algorithm
+ rep = None # bench representation algorithm
revision_range = '0:'
regression_range = '0:'
latest_revision = None
@@ -329,8 +329,6 @@
title = value
elif option == "-m":
rep = value
- if rep not in ["avg", "min", "med"]:
- raise Exception("Invalid -m representative: %s" % rep)
elif option == "-o":
redirect_stdout(value)
elif option == "-r":
diff --git a/bench/bench_util.py b/bench/bench_util.py
index 3b150a0..3abdee8 100644
--- a/bench/bench_util.py
+++ b/bench/bench_util.py
@@ -45,11 +45,41 @@
Max = _ExtremeType(1, "Max")
Min = _ExtremeType(-1, "Min")
-def parse(settings, lines, representative='avg'):
+class _ListAlgorithm(object):
+ """Algorithm for selecting the representation value from a given list.
+ representation is one of 'avg', 'min', 'med', '25th' (average, minimum,
+ median, 25th percentile)"""
+ def __init__(self, data, representation=None):
+ if not representation:
+ representation = 'avg' # default algorithm is average
+ self._data = data
+ self._len = len(data)
+ if representation == 'avg':
+ self._rep = sum(self._data) / self._len
+ else:
+ self._data.sort()
+ if representation == 'min':
+ self._rep = self._data[0]
+ else:
+ # for percentiles, we use the value below which x% of values are
+ # found, which allows for better detection of quantum behaviors.
+ if representation == 'med':
+ x = int(round(0.5 * self._len + 0.5))
+ elif representation == '25th':
+ x = int(round(0.25 * self._len + 0.5))
+ else:
+ raise Exception("invalid representation algorithm %s!" %
+ representation)
+ self._rep = self._data[x - 1]
+
+ def compute(self):
+ return self._rep
+
+def parse(settings, lines, representation='avg'):
"""Parses bench output into a useful data structure.
({str:str}, __iter__ -> str) -> [BenchDataPoint]
- representative is one of 'avg', 'min', 'med' (average, mean, median)."""
+ representation should match one of those defined in class _ListAlgorithm."""
benches = []
current_bench = None
@@ -85,26 +115,11 @@
current_time_type = new_time.group(1)
iters = [float(i) for i in
new_time.group(2).strip().split(',')]
- iters.sort()
- iter_len = len(iters)
- if representative == 'avg':
- rep = sum(iters) / iter_len
- elif representative == 'min':
- rep = iters[0]
- elif representative == 'med':
- if iter_len % 2:
- rep = (iters[iter_len / 2] +
- iters[iter_len / 2 - 1]) / 2
- else:
- rep = iters[iter_len / 2]
- else:
- raise Exception("invalid representative algorithm %s!" %
- representative)
benches.append(BenchDataPoint(
current_bench
, current_config
, current_time_type
- , rep
+ , _ListAlgorithm(iters, representation).compute()
, settings))
return benches