Skip to content

Commit 6aa36d1

Browse files
Initial commit
0 parents  commit 6aa36d1

14 files changed

+2481
-0
lines changed

README.md

Lines changed: 410 additions & 0 deletions
Large diffs are not rendered by default.

benchmark.py

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# -*- coding: utf-8 -*-
2+
from timeit import default_timer as timer
3+
4+
###
5+
# This file will usually not need any alteration.
6+
###
7+
8+
#
9+
10+
# Class to wrap a benchmark (helper functions)
11+
class Benchmark(object):
12+
def __init__(self):
13+
self.totalTime = {}
14+
self.iterations = {}
15+
self.startTime = {}
16+
self.depth = 0
17+
self.events = []
18+
# True will make all benchmark instances log their actions in an easy to follow manner
19+
# Might however use up more memory as each action is logged - defaults to False. Use with benchmark.printEvents()
20+
self.verbose = False
21+
22+
def __str__(self):
23+
totalTimePrint = ', '.join('"%s": %.6f'%(key, value) for key, value in self.totalTime.items())
24+
iterationsPrint = ', '.join('"%s": %d'%(key, value) for key, value in self.iterations.items())
25+
return "Benchmark <Total time: {%s}, iterations: {%s}>"%(totalTimePrint, iterationsPrint)
26+
def __repr__(self):
27+
totalTimePrint = ', '.join('"%s": %.6f'%(key, value) for key, value in self.totalTime.items())
28+
iterationsPrint = ', '.join('"%s": %d'%(key, value) for key, value in self.iterations.items())
29+
return "Benchmark <Total time: {%s}, iterations: {%s}>"%(totalTimePrint, iterationsPrint)
30+
31+
def __add__(self, other):
32+
self.mergeDictionaries(self.totalTime, other.totalTime)
33+
self.mergeDictionaries(self.iterations, other.iterations)
34+
self.mergeDictionaries(self.startTime, other.startTime)
35+
return self
36+
def __radd__(self, other):
37+
return self.__add__(other)
38+
39+
def asTables(self):
40+
timeLatex = """$\\begin{array}{l | l}
41+
\\text{name} & \\text{time }s\\\\
42+
\\hline\n """
43+
iterationsLatex = """$\\begin{array}{l | l}
44+
\\text{name} & \\text{iterations}\\\\
45+
\\hline\n """
46+
47+
for key, value in self.totalTime.items():
48+
timeLatex += "\\text{%s}&%f\\\\\n"%(key, value)
49+
for key, value in self.iterations.items():
50+
iterationsLatex += "\\text{%s}&%d\\\\\n"%(key, value)
51+
52+
timeLatex += "\\end{array}$"
53+
iterationsLatex += "\\end{array}$"
54+
55+
return (timeLatex, iterationsLatex)
56+
57+
def mergeDictionaries(self, a, b):
58+
for key in b.keys():
59+
if key not in a:
60+
a[key] = b[key]
61+
else:
62+
a[key] += b[key]
63+
64+
def start(self, name = "default"):
65+
t = timer()
66+
67+
if ":" in name or "," in name or "-" in name:
68+
raise ValueError("A benchmark name may not contain characters ':', '-' or ','")
69+
70+
if name in self.startTime:
71+
raise ValueError("Benchmark for %s is already in progress, please stop benchmark first"%name)
72+
73+
self.startTime[name] = t
74+
75+
if self.verbose:
76+
self.events.append(("start", name, self.depth, None))
77+
self.depth += 1
78+
79+
def stop(self, name = "default"):
80+
t = timer()
81+
82+
if ":" in name or "," in name or "-" in name:
83+
raise ValueError("A benchmark name may not contain characters ':', '-' or ','")
84+
85+
if name not in self.startTime:
86+
raise ValueError("Benchmark for %s cannot be stopped before it has been started"%name)
87+
88+
if name not in self.totalTime:
89+
self.totalTime[name] = 0
90+
91+
timeTaken = t - self.startTime[name]
92+
self.totalTime[name] += timeTaken
93+
del self.startTime[name]
94+
95+
if self.verbose:
96+
self.depth -= 1
97+
self.events.append(("stop", name, self.depth, timeTaken))
98+
99+
def iterate(self, name = "default"):
100+
if ":" in name or "," in name or "-" in name:
101+
raise ValueError("A benchmark name may not contain characters ':', '-' or ','")
102+
103+
if name not in self.iterations:
104+
self.iterations[name] = 0
105+
106+
self.iterations[name] += 1
107+
108+
if self.verbose:
109+
self.events.append(("iterate", name, self.depth, None))
110+
111+
def printEvents(self):
112+
if self.verbose == False or len(self.events) == 0:
113+
print "It seems like no events were captured. Try setting verbose = True on the benchmark instance"
114+
115+
i = 0
116+
while i < len(self.events):
117+
type, name, depth, timeTaken = self.events[i]
118+
if type == "iterate":
119+
start = i
120+
# Group identical iterations to preserve output length
121+
for j in range(i + 1, len(self.events)):
122+
otherType, otherName, otherDepth, otherTime = self.events[j]
123+
if otherType == type and otherName == name:
124+
i += 1
125+
else:
126+
break
127+
# Print number of occurances if multiple iterations followed each other
128+
if start == i:
129+
print "\t" * depth + "🔂 %s"%name
130+
else:
131+
print "\t" * depth + "🔂 %s x %d"%(name, i - start + 1)
132+
elif type == "start":
133+
print "\t" * depth + "▶️ %s"%name
134+
elif type == "stop":
135+
print "\t" * depth + "⏹ %s (%f s)"%(name, timeTaken)
136+
i += 1
137+
138+
@classmethod
139+
def max(self, benchmarks):
140+
benchmark = Benchmark()
141+
142+
totalTime = {}
143+
iterations = {}
144+
145+
for b in benchmarks:
146+
for key, value in b.totalTime.items():
147+
if key not in totalTime:
148+
totalTime[key] = []
149+
totalTime[key].append(value)
150+
for key, value in b.iterations.items():
151+
if key not in iterations:
152+
iterations[key] = []
153+
iterations[key].append(value)
154+
155+
for key, values in totalTime.items():
156+
benchmark.totalTime[key] = max(values)
157+
for key, values in iterations.items():
158+
benchmark.iterations[key] = max(values)
159+
160+
return benchmark
161+
162+
@classmethod
163+
def min(self, benchmarks):
164+
benchmark = Benchmark()
165+
166+
totalTime = {}
167+
iterations = {}
168+
169+
for b in benchmarks:
170+
for key, value in b.totalTime.items():
171+
if key not in totalTime:
172+
totalTime[key] = []
173+
totalTime[key].append(value)
174+
for key, value in b.iterations.items():
175+
if key not in iterations:
176+
iterations[key] = []
177+
iterations[key].append(value)
178+
179+
for key, values in totalTime.items():
180+
benchmark.totalTime[key] = min(values)
181+
for key, values in iterations.items():
182+
benchmark.iterations[key] = min(values)
183+
184+
return benchmark
185+
186+
@classmethod
187+
def average(self, benchmarks):
188+
benchmark = Benchmark()
189+
190+
totalTime = {}
191+
iterations = {}
192+
193+
average = lambda x : sum(x) / len(x)
194+
195+
for b in benchmarks:
196+
for key, value in b.totalTime.items():
197+
if key not in totalTime:
198+
totalTime[key] = []
199+
totalTime[key].append(value)
200+
for key, value in b.iterations.items():
201+
if key not in iterations:
202+
iterations[key] = []
203+
iterations[key].append(value)
204+
205+
for key, values in totalTime.items():
206+
benchmark.totalTime[key] = average(values)
207+
for key, values in iterations.items():
208+
benchmark.iterations[key] = average(values)
209+
210+
return benchmark

benchmark.sagews

Lines changed: 254 additions & 0 deletions
Large diffs are not rendered by default.

benchmark.sagews.html

Lines changed: 233 additions & 0 deletions
Large diffs are not rendered by default.

compile_appendix.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env bash
2+
3+
# This scripts take all python source code files and
4+
# format them to be syntax highlit and includable in LaTex.
5+
# All output files will be in ./appendices.
6+
7+
# Create the (temporary) directory ./appendices if needed
8+
mkdir -p appendices
9+
10+
# Create a file to be included in LaTex
11+
echo "% This file should be included in the article" > appendices/appendices.tex
12+
13+
# For each python file
14+
ls | grep ".py$" | while read -r filename ; do
15+
# Get LaTeX file name
16+
safeName=$(echo "$filename" | sed -e "s/_/\\\_/g")
17+
out=$(echo "$filename" | sed -e "s/.py/.tex/g")
18+
# Write LaTeX heading
19+
echo "\\chapter{$safeName}" > "appendices/$out"
20+
echo "\\begin{minted}[frame=lines, framesep=2mm, baselinestretch=1.2, bgcolor=white, fontsize=\\footnotesize, linenos]{python}" >> "appendices/$out"
21+
# Append file content
22+
cat $filename >> "appendices/$out"
23+
echo "" >> "appendices/$out"
24+
# Append LaTeX footer
25+
echo "\end{minted}" >> "appendices/$out"
26+
# Append filename to included in appendices
27+
echo "\\input{appendices/$out}" >> appendices/appendices.tex
28+
done
29+
30+
31+
32+
# Zip the appendices
33+
zip -r appendices.zip appendices
34+
35+
# Remove the temporary folder
36+
rm -r appendices

0 commit comments

Comments
 (0)