benchrun.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. """
  2. Downloaded from https://code.google.com/p/benchrun/
  3. A benchmark is defined by creating a subclass of Benchmark.
  4. The subclass should define a method run() that executes the code
  5. to be timed and returns the elapsed time in seconds (as a float),
  6. or None if the benchmark should be skipped.
  7. See fibonacci.py for example.
  8. """
  9. import sys
  10. if sys.platform=='win32':
  11. from time import clock
  12. else:
  13. from time import time as clock
  14. # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/302478
  15. def combinations(*seqin):
  16. def rloop(seqin,comb):
  17. if seqin:
  18. for item in seqin[0]:
  19. newcomb = comb + [item]
  20. for item in rloop(seqin[1:],newcomb):
  21. yield item
  22. else:
  23. yield comb
  24. return rloop(seqin,[])
  25. class Benchmark:
  26. sort_by = []
  27. reference = None
  28. def __init__(self):
  29. self.pnames = []
  30. self.pvalues = []
  31. self.results = []
  32. self.results_dict = {}
  33. for pname in self.parameters:
  34. value = getattr(self, pname)
  35. self.pnames.append(pname)
  36. self.pvalues.append(value)
  37. self.pcombos = list(combinations(*self.pvalues))
  38. if self.reference:
  39. self.reference_param = self.reference[0]
  40. self.reference_value = self.reference[1]
  41. def time_all(self):
  42. """Run benchmark for all versions and parameters."""
  43. for params in self.pcombos:
  44. args = dict(zip(self.pnames, params))
  45. t = self.run(**args)
  46. self.results.append(tuple(params) + (t,))
  47. self.results_dict[tuple(params)] = t
  48. def sort_results(self):
  49. sort_keys = []
  50. for name in self.sort_by:
  51. sort_keys += [self.pnames.index(name)]
  52. for i, name in enumerate(self.pnames):
  53. if i not in sort_keys:
  54. sort_keys += [i]
  55. def key(v):
  56. return list(v[i] for i in sort_keys)
  57. self.results.sort(key=key)
  58. def get_factor(self, pvalues, time):
  59. if not self.reference or not time:
  60. return None
  61. pvalues = list(pvalues)
  62. i = self.pnames.index(self.reference_param)
  63. if pvalues[i] == self.reference_value:
  64. return None
  65. else:
  66. pvalues[i] = self.reference_value
  67. ref = self.results_dict[tuple(pvalues)]
  68. if ref == None:
  69. return None
  70. return ref / time
  71. def print_result(self):
  72. """Run benchmark for all versions and parameters and print results
  73. in tabular form to the standard output."""
  74. self.time_all()
  75. self.sort_results()
  76. print "=" * 78
  77. print
  78. print self.__class__.__name__
  79. print self.__doc__, "\n"
  80. colwidth = 15
  81. reftimes = {}
  82. ts = "seconds"
  83. if self.reference:
  84. ts += " (x faster than " + (str(self.reference_value)) + ")"
  85. print " ", " ".join([str(r).ljust(colwidth) for r in self.pnames + [ts]])
  86. print "-"*79
  87. rows = []
  88. for vals in self.results:
  89. pvalues = vals[:-1]
  90. time = vals[-1]
  91. if time == None:
  92. stime = "(n/a)"
  93. else:
  94. stime = "%.8f" % time
  95. factor = self.get_factor(pvalues, time)
  96. if factor != None:
  97. stime += (" (%.2f)" % factor)
  98. vals = pvalues + (stime,)
  99. row = [str(val).ljust(colwidth) for val in vals]
  100. print " ", " ".join(row)
  101. print