11 re_prefix = "\([0-9]+\) (?:# )?"
12 re_date = re.compile('^Date: (.*)')
13 re_testing = re.compile('^('+re_prefix+')?\s*Testing "(.*)" in (.*):\s*$')
14 re_commit = re.compile('.*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*, commit: (.*)')
15 re_commithash = re.compile('([0-9a-f]{7})(-dirty)? \(')
16 re_assertion = re.compile('^('+re_prefix+')?!\s*(.*?)\s+(\S+)\s*$')
17 re_perf = re.compile('^('+re_prefix+')?!\s*(.*?)\s+PERF:\s*(.*?)\s+(\S+)\s*$')
18 re_perfaxis = re.compile('axis="([^"]+)"')
21 def __init__(self, name=None, units=None):
26 if self.units and self.name:
27 return "%s [%s]" % (self.name, self.units)
32 def __repr__(self): return "Axis(name=%s units=%s, id=%s)" % (self.name, self.units, hex(id(self)))
35 def __init__(self, name, units, axis):
39 def __repr__(self): return "Column(name=%s units=%s axis=%s)" % (self.name, self.units, repr(self.axis))
42 def __init__(self, graph, date):
45 def __getitem__(self, column):
47 return dict.__getitem__(self, column)
51 d = time.gmtime(time.mktime(self.date))
52 return "Date.UTC(%s, %s, %s, %s, %s, %s)" % \
53 (d.tm_year, d.tm_mon-1, d.tm_mday, d.tm_hour, d.tm_min, d.tm_sec)
56 def __init__(self, id, title):
58 self.columns_ordered = []
64 self.axes_ordered = []
66 def __getitem__(self, date):
68 rownum = self.date2row[date]
70 rownum = len(self.rows)
71 self.date2row[date] = rownum
73 return self.rows[rownum]
75 self.rows[rownum:rownum] = [Row(self, date)]
76 return self.rows[rownum]
78 def addValue(self, date, col, val, units):
81 if not self.columns.has_key(col):
82 axis=self.getAxis(units) or self.addAxis(units, Axis(units=units))
83 column = Column(col, units, axis)
84 self.columns[col] = column
85 self.columns_ordered.append(column)
87 column = self.columns[col]
88 self.columns_ordered.remove(column)
89 self.columns_ordered.append(column)
90 self.columns[col].units=units
91 self.columns[col].axis.units=units
93 def addAxis(self, key, axis):
97 def setAxis(self, col, key):
98 self.columns[col].axis = self.getAxis(key) or self.addAxis(key, Axis(name=key))
100 def getAxis(self, key):
101 if not self.axes.has_key(key): return None
102 return self.axes[key]
104 def findRanges(self):
105 for axis in self.axes.values():
106 cols = [col for col in self.columns.values() if col.axis == axis]
111 values = np.array([row[col.name] for row in self.rows if row[col.name] != None], np.float64)
112 if low == None and high == None:
113 lastmonth = values[-30:]
114 median = np.median(lastmonth)
118 if (values > high).any() or (values < low).any():
121 axis.yrange_max = high
122 axis.yrange_min = low
124 axis.yrange_max = None
125 axis.yrange_min = None
127 def fixupAxisNumbers(self):
128 # Sort axes according to the columns and number them
130 for column in self.columns_ordered:
132 if axis not in self.axes_ordered:
133 self.axes_ordered.insert(0, axis)
137 for axis in self.axes_ordered:
143 window.chart = new Highcharts.StockChart({
145 renderTo: '"""+self.id+"""'
153 text: '"""+self.title+"""'
158 verticalAlign: "top",
163 formatter: function() {
164 var s = '<b>'+ Highcharts.dateFormat('%a, %d %b %Y %H:%M:%S', this.x) +'</b><br/>';
165 s += commitMap[this.x].msg;
166 $.each(this.points, function(i, point) {
167 s += '<br/><span style="color:'+ point.series.color+';">'+ point.series.name +'</span>: '+point.y;
172 whiteSpace: 'normal',
179 click: function(event) {
180 var lastpoint = null;
181 for (var i in this.data) {
182 if (event.point == this.data[i]) {
183 if (i > 0) lastpoint = this.data[i-1];
188 window.location = "http://os.inf.tu-dresden.de/~jsteckli/cgi-bin/cgit.cgi/nul/log/?qt=range&q="+commitMap[lastpoint.x].hash+'..'+commitMap[event.point.x].hash;
190 window.location = "http://os.inf.tu-dresden.de/~jsteckli/cgi-bin/cgit.cgi/nul/log/?id="+commitMap[event.point.x].hash;
196 for axis in self.axes_ordered:
198 print "\t\t\t\t\tlineWidth: 1,"
199 print "\t\t\t\t\tlabels: { align: 'right', x: -3 },"
200 print "\t\t\t\t\ttitle: { text: '%s' }," % axis.getLabel()
201 #print "\t\t\t\t\tplotBands: { from: %s, to: %s, color: '#eee' }," % (col.low, col.high)
202 if axis.yrange_min: print "\t\t\t\t\tmin: %s," % axis.yrange_min
203 if axis.yrange_max: print "\t\t\t\t\tmax: %s," % axis.yrange_max
209 for col in self.columns_ordered:
210 print "\t\t\t\t{ name: '%s [%s]', yAxis: %d, data: [" % (col.name, col.units, col.axis.num)
212 for row in self.rows:
214 if val == None: val = "null"
215 print "\t\t\t\t\t[%s, %s], " % (row.getDate(), val)
226 date = time.localtime(time.time())
228 for line in sys.stdin.readlines():
231 match = re_date.match(line)
233 date = time.strptime(match.group(1), "%a, %d %b %Y %H:%M:%S +0200")
236 match = re_testing.match(line)
238 what = match.group(2)
239 where = match.group(3)
241 match = re_commit.match(what)
243 date = time.strptime(match.group(1), "%Y-%m-%d %H:%M:%S")
244 commit = match.group(2)
245 match = re_commithash.search(commit);
247 commithash = match.group(1)
250 commits[date] = (commit, commithash)
252 (basename, ext) = os.path.splitext(os.path.basename(where))
254 if what != "all": title = what
255 else: title = basename
257 graph = graphs[basename]
259 graph = Graph(basename, title)
260 graphs[basename] = graph
263 match = re_perf.match(line)
265 perfstr = match.group(3)
266 perf = perfstr.split()
274 if '=' in units: units = None
277 if match.group(4) != "ok":
280 graph.addValue(date, col, val, units)
282 match = re_perfaxis.search(perfstr)
284 graph.setAxis(col, match.group(1));
286 graphs = [g for g in graphs.values() if len(g.columns)]
287 graphs = sorted(graphs, key=lambda g: g.title.lower())
297 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
298 <title>NUL Performance Plots</title>
300 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
301 <script type="text/javascript">
303 for d in sorted(commits.iterkeys()):
305 print '\t\t\t%d: { msg: "%s", hash: "%s" },' % (1000*time.mktime(d), v[0].replace('"', '\\"'), str(v[1]).replace('"', '\\"'))
316 <h1>NUL Performance Plots</h1>
317 <script type="text/javascript" src="js/highstock.js"></script>
321 print " <li><a href='#%s'>%s</a></li>" % (graph.title, graph.title)
324 print " <h2><a name='%s'>%s</a></h2>" % (graph.title, graph.title)
325 print ' <div id="%s" style="height: 400px"></div>' % graph.id
332 # compile-command: "cat nul-nightly/nul_*.log|./wvperfpreprocess.py|./wvperf2html.py > graphs.html"