mirror of
https://github.com/golang/go
synced 2024-11-22 06:44:40 -07:00
dashboard: build most recent revision first
Will fill dashboard down the screen instead of up when builders get stuck and resume. Already live. Also delete dead benchmark code. I think it is safe to say that if/when we bring benchmarks back, we will use a different data model. Fixes #1228. R=adg CC=golang-dev https://golang.org/cl/4449059
This commit is contained in:
parent
43b97ce69b
commit
63d531a83e
@ -1,62 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>{{benchmark}} - Benchmarks - Go Dashboard</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<ul class="menu">
|
|
||||||
<li><a href="/">Build Status</a></li>
|
|
||||||
<li><a href="/package">Packages</a></li>
|
|
||||||
<li><a href="/project">Projects</a></li>
|
|
||||||
<li><a href="/benchmarks">Benchmarks</a></li>
|
|
||||||
<li><a href="http://golang.org/">golang.org</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h1>Go Dashboard</h1>
|
|
||||||
|
|
||||||
<h2>{{benchmark}}</h2>
|
|
||||||
|
|
||||||
<a href="{{benchmark}}?fmt=json">json</a>
|
|
||||||
|
|
||||||
{% for g in graphs %}
|
|
||||||
<h3>{{g.builder}}</h3>
|
|
||||||
{% if g.url %}
|
|
||||||
<img src="{{g.url}}&chs=600x150&chf=bg,s,00000000&chco=000000ff&chls=1,1,0">
|
|
||||||
{% else %}
|
|
||||||
(no data available)
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<br><br>
|
|
||||||
|
|
||||||
<table class="alternate" cellpadding="0" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
{% for b in builders %}
|
|
||||||
<th class="builder">{{b.goos}}<br>{{b.goarch}}<br>{{b.note}}</th>
|
|
||||||
{% endfor %}
|
|
||||||
<th></th>
|
|
||||||
<th></th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{% for r in revs %}
|
|
||||||
<tr>
|
|
||||||
<td class="revision"><span class="hash"><a href="https://code.google.com/p/go/source/detail?r={{r.node}}">{{r.node|slice:":12"}}</a></span></td>
|
|
||||||
|
|
||||||
{% for ns in r.ns_by_builder %}
|
|
||||||
<td class="result">
|
|
||||||
{% if ns %}
|
|
||||||
{{ns}}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% endfor %}
|
|
||||||
<td class="user">{{r.user|escape}}</td>
|
|
||||||
<td class="date">{{r.date|escape}}</td>
|
|
||||||
<td class="desc">{{r.shortdesc|escape}}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,46 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Benchmarks - Go Dashboard</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<ul class="menu">
|
|
||||||
<li><a href="/">Build Status</a></li>
|
|
||||||
<li><a href="/package">Packages</a></li>
|
|
||||||
<li><a href="/project">Projects</a></li>
|
|
||||||
<li>Benchmarks</li>
|
|
||||||
<li><a href="http://golang.org/">golang.org</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h1>Go Dashboard</h1>
|
|
||||||
|
|
||||||
<h2>Benchmarks</h2>
|
|
||||||
|
|
||||||
<table class="alternate" cellpadding="0" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
{% for b in builders %}
|
|
||||||
<th class="builder">{{b.goos}}<br>{{b.goarch}}<br>{{b.note}}</th>
|
|
||||||
{% endfor %}
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{% for bm in rows %}
|
|
||||||
<tr>
|
|
||||||
<td class="name"><a href="/benchmarks/{{bm.name}}">{{bm.name}}</a></td>
|
|
||||||
|
|
||||||
{% for bl in bm.builders %}
|
|
||||||
<td class="result">
|
|
||||||
{% if bl.url %}
|
|
||||||
<img src="{{bl.url}}" />
|
|
||||||
{% else %}
|
|
||||||
<img src="/benchmarks/single?benchmark={{bm.name}}&builder={{bl.name}}" />
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% endfor %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -44,21 +44,12 @@ class Commit(db.Model):
|
|||||||
desc = db.BlobProperty()
|
desc = db.BlobProperty()
|
||||||
|
|
||||||
# This is the list of builds. Each element is a string of the form <builder
|
# This is the list of builds. Each element is a string of the form <builder
|
||||||
# name> "`" <log hash>. If the log hash is empty, then the build was
|
# name> '`' <log hash>. If the log hash is empty, then the build was
|
||||||
# successful.
|
# successful.
|
||||||
builds = db.StringListProperty()
|
builds = db.StringListProperty()
|
||||||
|
|
||||||
fail_notification_sent = db.BooleanProperty()
|
fail_notification_sent = db.BooleanProperty()
|
||||||
|
|
||||||
class Benchmark(db.Model):
|
|
||||||
name = db.StringProperty()
|
|
||||||
version = db.IntegerProperty()
|
|
||||||
|
|
||||||
class BenchmarkResults(db.Model):
|
|
||||||
builder = db.StringProperty()
|
|
||||||
benchmark = db.StringProperty()
|
|
||||||
data = db.ListProperty(long) # encoded as [-1, num, iterations, nsperop]*
|
|
||||||
|
|
||||||
class Cache(db.Model):
|
class Cache(db.Model):
|
||||||
data = db.BlobProperty()
|
data = db.BlobProperty()
|
||||||
expire = db.IntegerProperty()
|
expire = db.IntegerProperty()
|
||||||
@ -69,12 +60,6 @@ class Cache(db.Model):
|
|||||||
class CompressedLog(db.Model):
|
class CompressedLog(db.Model):
|
||||||
log = db.BlobProperty()
|
log = db.BlobProperty()
|
||||||
|
|
||||||
# For each builder, we store the last revision that it built. So, if it
|
|
||||||
# crashes, it knows where to start up from. The key names for these objects are
|
|
||||||
# "hw-" <builder name>
|
|
||||||
class Highwater(db.Model):
|
|
||||||
commit = db.StringProperty()
|
|
||||||
|
|
||||||
N = 30
|
N = 30
|
||||||
|
|
||||||
def cache_get(key):
|
def cache_get(key):
|
||||||
@ -165,34 +150,40 @@ class MainPage(webapp.RequestHandler):
|
|||||||
class GetHighwater(webapp.RequestHandler):
|
class GetHighwater(webapp.RequestHandler):
|
||||||
def get(self):
|
def get(self):
|
||||||
builder = self.request.get('builder')
|
builder = self.request.get('builder')
|
||||||
|
key = 'todo-%s' % builder
|
||||||
key = 'hw-%s' % builder
|
response = memcache.get(key)
|
||||||
node = memcache.get(key)
|
if response is None:
|
||||||
if node is None:
|
# Fell out of memcache. Rebuild from datastore results.
|
||||||
hw = Highwater.get_by_key_name('hw-%s' % builder)
|
# We walk the commit list looking for nodes that have not
|
||||||
if hw is None:
|
# been built by this builder and record the *parents* of those
|
||||||
# If no highwater has been recorded for this builder,
|
# nodes, because each builder builds the revision *after* the
|
||||||
# we go back N+1 commits and return that.
|
# one return (because we might not know about the latest
|
||||||
q = Commit.all()
|
# revision).
|
||||||
q.order('-__key__')
|
q = Commit.all()
|
||||||
c = q.fetch(N+1)[-1]
|
q.order('-__key__')
|
||||||
node = c.node
|
todo = []
|
||||||
else:
|
need = False
|
||||||
# if the proposed hw is too old, bump it forward
|
first = None
|
||||||
node = hw.commit
|
for c in q.fetch(N+1):
|
||||||
found = False
|
if first is None:
|
||||||
q = Commit.all()
|
first = c
|
||||||
q.order('-__key__')
|
if need:
|
||||||
recent = q.fetch(N+1)
|
todo.append(c.node)
|
||||||
for c in recent:
|
need = not built(c, builder)
|
||||||
if c.node == node:
|
if not todo:
|
||||||
found = True
|
todo.append(first.node)
|
||||||
break
|
response = ' '.join(todo)
|
||||||
if not found:
|
memcache.set(key, response, 3600)
|
||||||
node = recent[-1].node
|
|
||||||
memcache.set(key, node, 3600)
|
|
||||||
self.response.set_status(200)
|
self.response.set_status(200)
|
||||||
self.response.out.write(node)
|
if self.request.get('all') != 'yes':
|
||||||
|
response = response.split()[0]
|
||||||
|
self.response.out.write(response)
|
||||||
|
|
||||||
|
def built(c, builder):
|
||||||
|
for b in c.builds:
|
||||||
|
if b.startswith(builder+'`'):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def auth(req):
|
def auth(req):
|
||||||
k = req.get('key')
|
k = req.get('key')
|
||||||
@ -204,32 +195,10 @@ class SetHighwater(webapp.RequestHandler):
|
|||||||
self.response.set_status(403)
|
self.response.set_status(403)
|
||||||
return
|
return
|
||||||
|
|
||||||
builder = self.request.get('builder')
|
# Allow for old builders.
|
||||||
newhw = self.request.get('hw')
|
# This is a no-op now: we figure out what to build based
|
||||||
q = Commit.all()
|
# on the current dashboard status.
|
||||||
q.filter('node =', newhw)
|
return
|
||||||
c = q.get()
|
|
||||||
if c is None:
|
|
||||||
self.response.set_status(404)
|
|
||||||
return
|
|
||||||
|
|
||||||
# if the proposed hw is too old, bump it forward
|
|
||||||
found = False
|
|
||||||
q = Commit.all()
|
|
||||||
q.order('-__key__')
|
|
||||||
recent = q.fetch(N+1)
|
|
||||||
for c in recent:
|
|
||||||
if c.node == newhw:
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
if not found:
|
|
||||||
c = recent[-1]
|
|
||||||
|
|
||||||
key = 'hw-%s' % builder
|
|
||||||
memcache.delete(key)
|
|
||||||
hw = Highwater(key_name = key)
|
|
||||||
hw.commit = c.node
|
|
||||||
hw.put()
|
|
||||||
|
|
||||||
class LogHandler(webapp.RequestHandler):
|
class LogHandler(webapp.RequestHandler):
|
||||||
def get(self):
|
def get(self):
|
||||||
@ -330,14 +299,8 @@ class Build(webapp.RequestHandler):
|
|||||||
|
|
||||||
db.run_in_transaction(add_build)
|
db.run_in_transaction(add_build)
|
||||||
|
|
||||||
key = 'hw-%s' % builder
|
key = 'todo-%s' % builder
|
||||||
hw = Highwater.get_by_key_name(key)
|
|
||||||
if hw is None:
|
|
||||||
hw = Highwater(key_name = key)
|
|
||||||
hw.commit = node
|
|
||||||
hw.put()
|
|
||||||
memcache.delete(key)
|
memcache.delete(key)
|
||||||
memcache.delete('hw')
|
|
||||||
|
|
||||||
def mark_sent():
|
def mark_sent():
|
||||||
n = Commit.get_by_key_name(key_name)
|
n = Commit.get_by_key_name(key_name)
|
||||||
@ -373,279 +336,12 @@ def failed(c, builder):
|
|||||||
return len(p[1]) > 0
|
return len(p[1]) > 0
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class Benchmarks(webapp.RequestHandler):
|
|
||||||
def json(self):
|
|
||||||
q = Benchmark.all()
|
|
||||||
q.filter('__key__ >', Benchmark.get_or_insert('v002.').key())
|
|
||||||
bs = q.fetch(10000)
|
|
||||||
|
|
||||||
self.response.set_status(200)
|
|
||||||
self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
|
|
||||||
self.response.out.write('{"benchmarks": [')
|
|
||||||
|
|
||||||
sep = "\n\t"
|
|
||||||
for b in bs:
|
|
||||||
self.response.out.write('%s"%s"' % (sep, b.name))
|
|
||||||
sep = ",\n\t"
|
|
||||||
self.response.out.write('\n]}\n')
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
if self.request.get('fmt') == 'json':
|
|
||||||
return self.json()
|
|
||||||
|
|
||||||
self.response.set_status(200)
|
|
||||||
self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
|
|
||||||
page = memcache.get('bench')
|
|
||||||
if not page:
|
|
||||||
# use datastore as cache to avoid computation even
|
|
||||||
# if memcache starts dropping things on the floor
|
|
||||||
logging.error("memcache dropped bench")
|
|
||||||
page = cache_get('bench')
|
|
||||||
if not page:
|
|
||||||
logging.error("cache dropped bench")
|
|
||||||
num = memcache.get('hw')
|
|
||||||
if num is None:
|
|
||||||
q = Commit.all()
|
|
||||||
q.order('-__key__')
|
|
||||||
n = q.fetch(1)[0]
|
|
||||||
num = n.num
|
|
||||||
memcache.set('hw', num)
|
|
||||||
page = self.compute(num)
|
|
||||||
cache_set('bench', page, 600)
|
|
||||||
memcache.set('bench', page, 600)
|
|
||||||
self.response.out.write(page)
|
|
||||||
|
|
||||||
def compute(self, num):
|
|
||||||
benchmarks, builders = benchmark_list()
|
|
||||||
|
|
||||||
rows = []
|
|
||||||
for bm in benchmarks:
|
|
||||||
row = {'name':bm, 'builders': []}
|
|
||||||
for bl in builders:
|
|
||||||
key = "single-%s-%s" % (bm, bl)
|
|
||||||
url = memcache.get(key)
|
|
||||||
row['builders'].append({'name': bl, 'url': url})
|
|
||||||
rows.append(row)
|
|
||||||
|
|
||||||
path = os.path.join(os.path.dirname(__file__), 'benchmarks.html')
|
|
||||||
data = {
|
|
||||||
"builders": [builderInfo(b) for b in builders],
|
|
||||||
"rows": rows,
|
|
||||||
}
|
|
||||||
return template.render(path, data)
|
|
||||||
|
|
||||||
def post(self):
|
|
||||||
if not auth(self.request):
|
|
||||||
self.response.set_status(403)
|
|
||||||
return
|
|
||||||
|
|
||||||
builder = self.request.get('builder')
|
|
||||||
node = self.request.get('node')
|
|
||||||
if not validNode(node):
|
|
||||||
logging.error("Not valid node ('%s')", node)
|
|
||||||
self.response.set_status(500)
|
|
||||||
return
|
|
||||||
|
|
||||||
benchmarkdata = self.request.get('benchmarkdata')
|
|
||||||
benchmarkdata = binascii.a2b_base64(benchmarkdata)
|
|
||||||
|
|
||||||
def get_string(i):
|
|
||||||
l, = struct.unpack('>H', i[:2])
|
|
||||||
s = i[2:2+l]
|
|
||||||
if len(s) != l:
|
|
||||||
return None, None
|
|
||||||
return s, i[2+l:]
|
|
||||||
|
|
||||||
benchmarks = {}
|
|
||||||
while len(benchmarkdata) > 0:
|
|
||||||
name, benchmarkdata = get_string(benchmarkdata)
|
|
||||||
iterations_str, benchmarkdata = get_string(benchmarkdata)
|
|
||||||
time_str, benchmarkdata = get_string(benchmarkdata)
|
|
||||||
iterations = int(iterations_str)
|
|
||||||
time = int(time_str)
|
|
||||||
|
|
||||||
benchmarks[name] = (iterations, time)
|
|
||||||
|
|
||||||
q = Commit.all()
|
|
||||||
q.filter('node =', node)
|
|
||||||
n = q.get()
|
|
||||||
if n is None:
|
|
||||||
logging.error('Client asked for unknown commit while uploading benchmarks')
|
|
||||||
self.response.set_status(404)
|
|
||||||
return
|
|
||||||
|
|
||||||
for (benchmark, (iterations, time)) in benchmarks.items():
|
|
||||||
b = Benchmark.get_or_insert('v002.' + benchmark.encode('base64'), name = benchmark, version = 2)
|
|
||||||
key = '%s;%s' % (builder, benchmark)
|
|
||||||
r1 = BenchmarkResults.get_by_key_name(key)
|
|
||||||
if r1 is not None and (len(r1.data) < 4 or r1.data[-4] != -1 or r1.data[-3] != n.num):
|
|
||||||
r1.data += [-1L, long(n.num), long(iterations), long(time)]
|
|
||||||
r1.put()
|
|
||||||
key = "bench(%s,%s,%d)" % (benchmark, builder, n.num)
|
|
||||||
memcache.delete(key)
|
|
||||||
|
|
||||||
self.response.set_status(200)
|
|
||||||
|
|
||||||
class SingleBenchmark(webapp.RequestHandler):
|
|
||||||
"""
|
|
||||||
Fetch data for single benchmark/builder combination
|
|
||||||
and return sparkline url as HTTP redirect, also set memcache entry.
|
|
||||||
"""
|
|
||||||
def get(self):
|
|
||||||
benchmark = self.request.get('benchmark')
|
|
||||||
builder = self.request.get('builder')
|
|
||||||
key = "single-%s-%s" % (benchmark, builder)
|
|
||||||
|
|
||||||
url = memcache.get(key)
|
|
||||||
|
|
||||||
if url is None:
|
|
||||||
minr, maxr, bybuilder = benchmark_data(benchmark)
|
|
||||||
for bb in bybuilder:
|
|
||||||
if bb[0] != builder:
|
|
||||||
continue
|
|
||||||
url = benchmark_sparkline(bb[2])
|
|
||||||
|
|
||||||
if url is None:
|
|
||||||
self.response.set_status(500, "No data found")
|
|
||||||
return
|
|
||||||
|
|
||||||
memcache.set(key, url, 700) # slightly longer than bench timeout
|
|
||||||
|
|
||||||
self.response.set_status(302)
|
|
||||||
self.response.headers.add_header("Location", url)
|
|
||||||
|
|
||||||
def node(num):
|
def node(num):
|
||||||
q = Commit.all()
|
q = Commit.all()
|
||||||
q.filter('num =', num)
|
q.filter('num =', num)
|
||||||
n = q.get()
|
n = q.get()
|
||||||
return n
|
return n
|
||||||
|
|
||||||
def benchmark_data(benchmark):
|
|
||||||
q = BenchmarkResults.all()
|
|
||||||
q.order('__key__')
|
|
||||||
q.filter('benchmark =', benchmark)
|
|
||||||
results = q.fetch(100)
|
|
||||||
|
|
||||||
minr = 100000000
|
|
||||||
maxr = 0
|
|
||||||
for r in results:
|
|
||||||
if r.benchmark != benchmark:
|
|
||||||
continue
|
|
||||||
# data is [-1, num, iters, nsperop, -1, num, iters, nsperop, ...]
|
|
||||||
d = r.data
|
|
||||||
if not d:
|
|
||||||
continue
|
|
||||||
if [x for x in d[::4] if x != -1]:
|
|
||||||
# unexpected data framing
|
|
||||||
logging.error("bad framing for data in %s;%s" % (r.builder, r.benchmark))
|
|
||||||
continue
|
|
||||||
revs = d[1::4]
|
|
||||||
minr = min(minr, min(revs))
|
|
||||||
maxr = max(maxr, max(revs))
|
|
||||||
if minr > maxr:
|
|
||||||
return 0, 0, []
|
|
||||||
|
|
||||||
bybuilder = []
|
|
||||||
for r in results:
|
|
||||||
if r.benchmark != benchmark:
|
|
||||||
continue
|
|
||||||
d = r.data
|
|
||||||
if not d:
|
|
||||||
continue
|
|
||||||
nsbyrev = [-1 for x in range(minr, maxr+1)]
|
|
||||||
iterbyrev = [-1 for x in range(minr, maxr+1)]
|
|
||||||
for num, iter, ns in zip(d[1::4], d[2::4], d[3::4]):
|
|
||||||
iterbyrev[num - minr] = iter
|
|
||||||
nsbyrev[num - minr] = ns
|
|
||||||
bybuilder.append((r.builder, iterbyrev, nsbyrev))
|
|
||||||
|
|
||||||
return minr, maxr, bybuilder
|
|
||||||
|
|
||||||
def benchmark_graph(builder, minhash, maxhash, ns):
|
|
||||||
valid = [x for x in ns if x >= 0]
|
|
||||||
if not valid:
|
|
||||||
return ""
|
|
||||||
m = max(max(valid), 2*sum(valid)/len(valid))
|
|
||||||
s = ""
|
|
||||||
encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-"
|
|
||||||
for val in ns:
|
|
||||||
if val < 0:
|
|
||||||
s += "__"
|
|
||||||
continue
|
|
||||||
val = int(val*4095.0/m)
|
|
||||||
s += encoding[val/64] + encoding[val%64]
|
|
||||||
return ("http://chart.apis.google.com/chart?cht=lc&chxt=x,y&chxl=0:|%s|%s|1:|0|%g ns|%g ns&chd=e:%s" %
|
|
||||||
(minhash[0:12], maxhash[0:12], m/2, m, s))
|
|
||||||
|
|
||||||
def benchmark_sparkline(ns):
|
|
||||||
valid = [x for x in ns if x >= 0]
|
|
||||||
if not valid:
|
|
||||||
return ""
|
|
||||||
m = max(max(valid), 2*sum(valid)/len(valid))
|
|
||||||
# Encoding is 0-61, which is fine enough granularity for our tiny graphs. _ means missing.
|
|
||||||
encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
|
||||||
s = ''.join([x < 0 and "_" or encoding[int((len(encoding)-1)*x/m)] for x in ns])
|
|
||||||
url = "http://chart.apis.google.com/chart?cht=ls&chd=s:"+s+"&chs=80x20&chf=bg,s,00000000&chco=000000ff&chls=1,1,0"
|
|
||||||
return url
|
|
||||||
|
|
||||||
def benchmark_list():
|
|
||||||
q = BenchmarkResults.all()
|
|
||||||
q.order('__key__')
|
|
||||||
q.filter('builder = ', u'darwin-amd64')
|
|
||||||
benchmarks = [r.benchmark for r in q]
|
|
||||||
|
|
||||||
q = BenchmarkResults.all()
|
|
||||||
q.order('__key__')
|
|
||||||
q.filter('benchmark =', u'math_test.BenchmarkSqrt')
|
|
||||||
builders = [r.builder for r in q.fetch(20)]
|
|
||||||
|
|
||||||
return benchmarks, builders
|
|
||||||
|
|
||||||
class GetBenchmarks(webapp.RequestHandler):
|
|
||||||
def get(self):
|
|
||||||
benchmark = self.request.path[12:]
|
|
||||||
minr, maxr, bybuilder = benchmark_data(benchmark)
|
|
||||||
minhash = node(minr).node
|
|
||||||
maxhash = node(maxr).node
|
|
||||||
|
|
||||||
if self.request.get('fmt') == 'json':
|
|
||||||
self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
|
|
||||||
self.response.out.write('{ "min": "%s", "max": "%s", "data": {' % (minhash, maxhash))
|
|
||||||
sep = "\n\t"
|
|
||||||
for builder, iter, ns in bybuilder:
|
|
||||||
self.response.out.write('%s{ "builder": "%s", "iterations": %s, "nsperop": %s }' %
|
|
||||||
(sep, builder, str(iter).replace("L", ""), str(ns).replace("L", "")))
|
|
||||||
sep = ",\n\t"
|
|
||||||
self.response.out.write('\n}\n')
|
|
||||||
return
|
|
||||||
|
|
||||||
graphs = []
|
|
||||||
for builder, iter, ns in bybuilder:
|
|
||||||
graphs.append({"builder": builder, "url": benchmark_graph(builder, minhash, maxhash, ns)})
|
|
||||||
|
|
||||||
revs = []
|
|
||||||
for i in range(minr, maxr+1):
|
|
||||||
r = nodeInfo(node(i))
|
|
||||||
x = []
|
|
||||||
for _, _, ns in bybuilder:
|
|
||||||
t = ns[i - minr]
|
|
||||||
if t < 0:
|
|
||||||
t = None
|
|
||||||
x.append(t)
|
|
||||||
r["ns_by_builder"] = x
|
|
||||||
revs.append(r)
|
|
||||||
revs.reverse() # same order as front page
|
|
||||||
|
|
||||||
path = os.path.join(os.path.dirname(__file__), 'benchmark1.html')
|
|
||||||
data = {
|
|
||||||
"benchmark": benchmark,
|
|
||||||
"builders": [builderInfo(b) for b,_,_ in bybuilder],
|
|
||||||
"graphs": graphs,
|
|
||||||
"revs": revs,
|
|
||||||
}
|
|
||||||
self.response.out.write(template.render(path, data))
|
|
||||||
|
|
||||||
|
|
||||||
class FixedOffset(datetime.tzinfo):
|
class FixedOffset(datetime.tzinfo):
|
||||||
"""Fixed offset in minutes east from UTC."""
|
"""Fixed offset in minutes east from UTC."""
|
||||||
|
|
||||||
@ -731,9 +427,6 @@ application = webapp.WSGIApplication(
|
|||||||
|
|
||||||
('/init', Init),
|
('/init', Init),
|
||||||
('/build', Build),
|
('/build', Build),
|
||||||
('/benchmarks', Benchmarks),
|
|
||||||
('/benchmarks/single', SingleBenchmark),
|
|
||||||
('/benchmarks/.*', GetBenchmarks),
|
|
||||||
], debug=True)
|
], debug=True)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
<li>Build Status</li>
|
<li>Build Status</li>
|
||||||
<li><a href="/package">Packages</a></li>
|
<li><a href="/package">Packages</a></li>
|
||||||
<li><a href="/project">Projects</a></li>
|
<li><a href="/project">Projects</a></li>
|
||||||
<!-- <li><a href="/benchmarks">Benchmarks</a></li> -->
|
|
||||||
<li><a href="http://golang.org/">golang.org</a></li>
|
<li><a href="http://golang.org/">golang.org</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
<li><a href="/">Build Status</a></li>
|
<li><a href="/">Build Status</a></li>
|
||||||
<li>Packages</li>
|
<li>Packages</li>
|
||||||
<li><a href="/project">Projects</a></li>
|
<li><a href="/project">Projects</a></li>
|
||||||
<!-- <li><a href="/benchmarks">Benchmarks</a></li> -->
|
|
||||||
<li><a href="http://golang.org/">golang.org</a></li>
|
<li><a href="http://golang.org/">golang.org</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
<li><a href="/">Build Status</a></li>
|
<li><a href="/">Build Status</a></li>
|
||||||
<li><a href="/package">Packages</a></li>
|
<li><a href="/package">Packages</a></li>
|
||||||
<li>Projects</li>
|
<li>Projects</li>
|
||||||
<!-- <li><a href="/benchmarks">Benchmarks</a></li> -->
|
|
||||||
<li><a href="http://golang.org/">golang.org</a></li>
|
<li><a href="http://golang.org/">golang.org</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user