Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 164 additions & 12 deletions bleachermark.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@
('stupid benchmark', 'zero', 1, 0.0, 0)]
"""

from time import clock
# Support both Python 2 (using clock) and Python 3 (using perf_counter)
try:
from time import perf_counter
except (ImportError, AttributeError):
from time import clock as perf_counter

from copy import copy

#This part handles the ctrl-c interruption.
Expand Down Expand Up @@ -147,9 +152,9 @@ def run(self, i):
time_vals = [i]
intervalue = i
for fun in self._pipeline:
tim = clock()
tim = perf_counter()
intervalue = fun(intervalue)
time_vals.append( (clock()-tim, intervalue) )
time_vals.append( (perf_counter()-tim, intervalue) )
return time_vals


Expand Down Expand Up @@ -308,7 +313,7 @@ def fetch_data(self, format="dict"):
data.append( (label, fun_labels[i], run[0], m[0], m[1]) )
return data
else:
raise ValueError("Invalid argument to format: %s".format(format))
raise ValueError(f"Invalid argument to format: {format}")

def timings(self, transposed=False):
r"""
Expand Down Expand Up @@ -344,11 +349,8 @@ def averages(self):

"""
timings = self.timings(transposed=True)
res = {}
for bm in timings.keys():
totals = map(lambda a: sum(a)/len(a), timings[bm])
res[bm] = totals
return res
return {bm: [sum(t)/len(t) for t in timings[bm]]
for bm in timings.keys() }

def variances(self):
r"""
Expand All @@ -375,21 +377,24 @@ def stdvs(self):
"""
variances = self.variances()
import math
return {bm:map(math.sqrt, variances[bm]) for bm in variances}
return {bm: [math.sqrt(v) for v in variances[bm]]
for bm in variances}

def maxes(self):
r"""
Return the maximum running times of the benchmarks run.
"""
timings = self.timings(transposed=True)
return {bm:map(max, timings[bm]) for bm in timings}
return {bm: [max(t) for t in timings[bm]]
for bm in timings}

def mins(self):
r"""
Return the minimum running times of the benchmarks run.
"""
timings = self.timings(transposed=True)
return {bm:map(min, timings[bm]) for bm in timings}
return {bm: [min(t) for t in timings[bm]]
for bm in timings}

def pipeline_data(self):
r"""
Expand Down Expand Up @@ -427,8 +432,155 @@ def __add__(self, other):

return self

class SimpleBleachermark:
"""
Create a collection of benchmarks to evaluate the complexity of a function.

INPUT:

- ``data_generator`` -- a function taking a size argument, and
generating some data of this size at random
- ``function`` -- a function taking data generated by ``data_generator`` as input
- ``sizes`` -- a collection of sizes

EXAMPLES:

We want to evaluate the practical complexity of Python's sorting
algorithms according to the size of the list. First we write a
function to generate a random list of a give size::

>>> from random import randint
>>> def random_list(n):
... return [randint(0, n) for i in range(n)]

Then we create the collection of benchmarks::

>>> from bleachermark import *
>>> BB = SimpleBleachermark(random_list, sorted, sizes=[1,2,4,8])

We run the benchmark::

>>> BB.run()

The benchmark can be interrupted anytime with ^C, and resumed
later on by calling ``run`` again.

Now we can look at the timings::

>>> BB.timings() # random
{1: [6.000000000061512e-06, ... 5.000000000032756e-06],
2: [4.000000000004e-06, ... 2.9999999999752447e-06],
4: [4.999999999921734e-06, ... 9.000000000036756e-06],
8: [5.000000000032756e-06, ... 5.000000000032756e-06]}

and do some simple statistics on them::

>>> BB.averages() # random
{1: 4.670000000006613e-06,
2: 6.58999999999188e-06,
4: 1.1639999999993878e-05,
8: 1.8289999999996364e-05}
>>> BB.mins() # random
{1: 4.670000000006613e-06,
2: 6.58999999999188e-06,
4: 1.1639999999993878e-05,
8: 1.8289999999996364e-05}
>>> BB.maxs() # random
{1: 4.670000000006613e-06,
2: 6.58999999999188e-06,
4: 1.1639999999993878e-05,
8: 1.8289999999996364e-05}
"""
def __init__(self, data_generator, function, sizes):
r"""

"""
def gen(size):
return lambda run_id: data_generator(size)
self._bleachermark = Bleachermark([Benchmark([gen(size), function], label=size) for size in sizes])

def run(self):
return self._bleachermark.run()

def timings(self):
r"""
Return all measured timings.

EXAMPLES::

>>> from bleachermark import *
>>> from random import randint
>>> def random_list(n):
... return [randint(0, n) for i in range(n)]
>>> BB = SimpleBleachermark(random_list, sorted, sizes=[1,2,4,8])
>>> BB.run()
>>> BB.averages() # random
{1: 4.670000000006613e-06,
2: 6.58999999999188e-06,
4: 1.1639999999993878e-05,
8: 1.8289999999996364e-05}
"""
return {size: [t[1] for t in timings] for size,timings in self._bleachermark.timings().items()}

def averages(self):
"""
Return the averages of the timings

EXAMPLES::

>>> from bleachermark import *
>>> from random import randint
>>> def random_list(n):
... return [randint(0, n) for i in range(n)]
>>> BB = SimpleBleachermark(random_list, sorted, sizes=[1,2,4,8])
>>> BB.run()
>>> BB.averages() # random
{1: 4.670000000006613e-06,
2: 6.58999999999188e-06,
4: 1.1639999999993878e-05,
8: 1.8289999999996364e-05}
"""
return {size: average[1] for size,average in self._bleachermark.averages().items()}

def mins(self):
"""
Return the mins of the timings

EXAMPLES::

>>> from bleachermark import *
>>> from random import randint
>>> def random_list(n):
... return [randint(0, n) for i in range(n)]
>>> BB = SimpleBleachermark(random_list, sorted, sizes=[1,2,4,8])
>>> BB.run()
>>> BB.mins() # random
{1: 4.670000000006613e-06,
2: 6.58999999999188e-06,
4: 1.1639999999993878e-05,
8: 1.8289999999996364e-05}
"""
return {size: min[1] for size,min in self._bleachermark.mins().items()}

def maxes(self):
"""
Return the maxes of the timings

EXAMPLES::

>>> from bleachermark import *
>>> from random import randint
>>> def random_list(n):
... return [randint(0, n) for i in range(n)]
>>> BB = SimpleBleachermark(random_list, sorted, sizes=[1,2,4,8])
>>> BB.run()
>>> BB.maxes() # random
{1: 4.670000000006613e-06,
2: 6.58999999999188e-06,
4: 1.1639999999993878e-05,
8: 1.8289999999996364e-05}
"""
return {size: max[1] for size,max in self._bleachermark.maxes().items()}

#RUNNERS
# Runners are essentially iterators that produce the data that the bleachermark will store.
Expand Down