Two convenience classes for applying different scenarios (data) to different functions and measuring timing as a practical framework for optimizing performance. NOTE: time.clock() and time.time() resolution depend on system time.clock() may be more appropriate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | """classes for timing during development
by wolfgang resch, 070722
"""
from time import clock, time
#--- timer decorator -----------------------------------
class Timer(object):
def __init__(self, f):
self.__f=f
self.__name__=f.__name__
self.__doc__=f.__doc__
self.times=[]
def __call__(self, *args, **kwargs):
start=time()
result=self.__f(*args, **kwargs)
stop=time()
self.times.append(stop-start)
def report(self):
results = {'min':min(self.times)*1000, 'max':max(self.times)*1000, 'mean':sum(self.times)/len(self.times)*1000}
return self.__doc__.ljust(70) + "\t%(mean)6.5fms [%(min)6.5f - %(max)6.5f]" % results
def reset(self):
self.times=[]
#--- scenarios -------------------------------------------
class Scenario(object):
def __init__(self, **kw):
"""
pass each scenario as a kw={'desc':"", data:(), functions:()}
for each scenario each function is applied to the data and results are printed
"""
self.scenarios=kw
def run(self, nr_iter):
for title, scenario in self.scenarios.items():
print 50*'-' + "\n" + title.upper()
print scenario['desc']
for f in scenario['functions']:
for x in xrange(nr_iter):
f(*scenario['data'])
print "\t" + f.report()
f.reset()
#--- example: validators------------------------------------------
# validator takes a iterable object and checks if each element
# in the object is part of a defined alphabet
@Timer
def validate1(s, a):
"""validate1(s, a): list comprehension with a.index"""
try:
[a.index(x) for x in s]
return True
except:
return False
@Timer
def validate2(s,a):
"""validate2(s, a): for loop with a.index"""
for l in s:
try:
a.index(l)
except:
return False
return True
@Timer
def validate3(s,a):
"""validate3(s, a): list comprehension with (l in a)"""
return min([(l in a) for l in s])
@Timer
def validate4(s,a):
"""validate4(s, a): for loop with generator and (l in a)"""
for x in ((l in a) for l in s):
if not x:
return False
return True
@Timer
def validate5(s,a):
"""validate5(s,a): convert s to set and compare to set alphabet"""
return set(s).issubset(a)
#--- main-------------------------------------------------
if __name__=='__main__':
replications=1000
s_false="GATCTTGACGATGCGATGCGATG"*40 + "==" + "GATCTTGACGATGCGATGCGATG"*40
s_true=80*"GATCTTGACGATGCGATGCGATG" + "GA"
a=['G','A','T','C','R','W','B','C','M','T','Q','X','.','-','~','U']
testValidator = Scenario(scene_1={'desc':"Validator evaluates to true; alphabet is a list",
'data':(s_true, a),
'functions':(validate1, validate2, validate3, validate4, validate5)},
scene_2= {'desc':"Validator evaluates to false; alphabet is a list",
'data':(s_false, a),
'functions':(validate1, validate2, validate3, validate4, validate5)},
scene_3={'desc':"Validator evaluates to true; alphabet is a tuple",
'data':(s_true, tuple(a)),
'functions':( validate3, validate4, validate5)})
testValidator.run(1000)
-----------------------------
|
I like to systematically test different algorithms for some projects to help performance. This is mostly because I'm not a particularly good programmer, so i usually come up with slow ways of doing things. This is a very simple framework for putting functions through their paces, consisting of a timing decorator class and a class that applies different scenarios to different functions and measures timing. I did this b/c for some algorithms it's important to test different data as is the case for the validators in this example - these validators check if elements of a sequence s conform to an alphabet a. The performance of some algorithms depends on weather the validation fails or not. Please let me know any suggestions/corrections you may have.