24:58825476075c
Anton Shestakov <engored@ya.ru>, Sat, 23 May 2015 17:34:12 +0800
bench: additionally store time in (mark, cache) index

next change 25:a98e0e20561c
previous change 13:dce6d8966d49

viewer.py

Permissions: -rwxr-xr-x

Other formats: Feeds:
#!/usr/bin/env python
import colorsys
import json
import logging
import re
import sqlite3
import subprocess
from tornado.ioloop import IOLoop
from tornado.options import define, options
from tornado.web import Application, RequestHandler, URLSpec
from settings import DBPATH, HG, TEMPLATES, TESTHGREPO
from bench import MARKS
define('listen', metavar='IP', default='127.0.0.1')
define('port', metavar='PORT', default=8065, type=int)
define('xheaders', metavar='True|False', default=False, type=bool)
define('debug', metavar='True|False', default=False, type=bool)
def getinfo(revset):
output = subprocess.check_output([HG, 'log', '-R', TESTHGREPO, '-T', 'json', '-r', revset])
return json.loads(output)
class BaseHandler(RequestHandler):
def prepare(self):
self.conn = sqlite3.connect(DBPATH)
super(BaseHandler, self).prepare()
def on_finish(self):
self.conn.close()
class IndexHandler(BaseHandler):
def get(self):
self.redirect('results.html')
class ResultsHandler(BaseHandler):
def get(self, ext):
if ext == 'tsv':
self.results_tsv()
elif ext == 'asc':
self.results_asc()
elif ext == 'html':
self.results_html()
def getchangesets(self):
rev = self.get_argument('rev', 'tip')
revcount = 120
return getinfo('first({}:0, {})'.format(rev, revcount))
def getresults(self, changesets):
results = {}
limits = {
mark:
self.conn.execute(
'SELECT MIN(time), MAX(time) FROM results WHERE mark = ? AND cache = ?',
(mark, False)).fetchone()
+
self.conn.execute(
'SELECT MIN(time), MAX(time) FROM results WHERE mark = ? AND cache = ?',
(mark, True)).fetchone()
for mark in MARKS
}
for cset in changesets:
node = cset['node']
resultsq = self.conn.execute(
'SELECT mark, time, cache FROM results WHERE node = ?',
(node,))
for mark, time, cache in resultsq:
results.setdefault(node, {}).setdefault(mark, [None, None, None, None])
if not cache:
color = green_to_red(limits[mark][0:2], time) if time is not None else None
results[node][mark][0:2] = [time, color]
else:
color = green_to_red(limits[mark][2:4], time) if time is not None else None
results[node][mark][2:4] = [time, color]
return results
def results_tsv(self):
self.set_header('Content-Type', 'text/plain; charset=UTF-8')
changesets = self.getchangesets()
results = self.getresults(changesets)
self.write('rev\tnode')
for mark in MARKS:
self.write('\t{0} (without cache)\t{0} (with cache)'.format(mark))
self.write('\n')
for cset in changesets:
self.write('{rev}\t{node}'.format(**cset))
for mark in MARKS:
marks = results.get(cset['node'], {}).get(mark, ('', '', ''))
self.write('\t{0}\t{2}'.format(*marks))
self.write('\n')
self.finish()
def results_asc(self):
self.set_header('Content-Type', 'text/plain; charset=UTF-8')
rev = self.get_argument('rev', 'tip')
revcount = 120
regex = re.compile(r'^[-\\|/+ ]+([0-9a-f]{40})$')
template = '{rev}:{node|short} {tags} {date|isodate} {author|user} {desc|firstline|strip}\n {node}\n\n'
revset = 'first({}:0, {})'.format(rev, revcount)
cmd = [HG, 'log', '-R', TESTHGREPO, '-G', '-T', template, '-r', revset]
graph = subprocess.Popen(cmd, stdout=subprocess.PIPE)
while graph.poll() is None:
line = graph.stdout.readline()
matches = regex.findall(line)
for match in matches:
msg = []
rows = self.conn.execute(
'SELECT mark, time, cache FROM results WHERE node = ?',
(match,))
matchtimes = {}
for mark, time, cache in rows:
matchtimes.setdefault(mark, [None, None])
matchtimes[mark][1 if cache else 0] = time
for mark in MARKS:
msg.append('{mark}: {0:.2f}s/{1:.2f}s'.format(*matchtimes[mark], mark=mark))
line = line.replace(match, ' '.join(msg))
self.write(line)
self.finish()
def results_html(self):
changesets = self.getchangesets()
results = self.getresults(changesets)
self.render('results.html', changesets=changesets, marks=MARKS, results=results)
def green_to_red((low, high), value):
hue = (value - low) / (high - low) if high != low else 0.5
r, g, b = colorsys.hsv_to_rgb((1 - hue) * 0.3, 1, 1)
return (int(r * 255), int(g * 255), int(b * 255))
class Viewer(Application):
def __init__(self):
handlers = [
URLSpec(r'/', IndexHandler),
URLSpec(r'/results\.(html|tsv|asc)', ResultsHandler),
]
settings = dict(
template_path=TEMPLATES,
debug=options.debug
)
super(Viewer, self).__init__(handlers, **settings)
def listen(self, port, address='', **kwargs):
logging.info('{} is serving on {}:{}'.format(self.__class__.__name__, address, port))
super(Viewer, self).listen(port, address, **kwargs)
def main():
options.parse_command_line()
application = Viewer()
application.listen(options.port, address=options.listen, xheaders=options.xheaders)
IOLoop.instance().start()
if __name__ == '__main__':
main()