Commit 71c5971a authored by Zixian Cai's avatar Zixian Cai

Displaying timelines

parent 707abfdf
......@@ -16,7 +16,7 @@
from flask import Flask, render_template, request, flash, redirect, url_for
from mubench.conf import settings
from mubench.frontend.utils import group_stats_result
from mubench.frontend.web import changes
from mubench.frontend.web import changes, timeline
from mubench.frontend.web.storage import LocalStorage as storage
import click
import json
......@@ -25,26 +25,32 @@ app = Flask(__name__)
app.config['SECRET_KEY'] = settings.WEB_SECRET
@app.route("/<repo>/<rev>/<host>/visualize")
def result_visualize(repo, rev, host):
result = storage.load(repo, rev, host)
@app.route("/<repo>/<host>/timeline")
def result_timeline(repo, host):
pass
@app.route("/<repo>/<host>/<rev>/visualize")
def result_visualize(repo, host, rev):
result = storage.load(repo, host, rev)
return render_template("visualize.html", result=result)
@app.route("/<repo>/<rev>/<host>/store", methods=["POST"])
def result_store(repo, rev, host):
@app.route("/<repo>/<host>/<rev>/store", methods=["POST"])
def result_store(repo, host, rev):
if "logfile" not in request.files:
flash("No log file uploaded")
return redirect(url_for("index"))
logfile = request.files["logfile"]
storage.store(repo, rev, host, logfile.read())
timestamp = request.form.get("timestamp")
storage.store(repo, host, rev, timestamp, logfile.read())
return redirect(url_for("index"))
@app.route("/<repo>/<rev>/<host>/compare/<repo1>/<rev1>/<host1>")
def result_compare(repo, rev, host, repo1, rev1, host1):
result = storage.load(repo, rev, host)
result1 = storage.load(repo1, rev1, host1)
@app.route("/<repo>/<host>/<rev>/compare/<repo1>/<host1>/<rev1>")
def result_compare(repo, host, rev, repo1, host1, rev1):
result = storage.load(repo, host, rev)
result1 = storage.load(repo1, host1, rev1)
return render_template("changes.html",
result=changes.compare(result, result1))
......@@ -69,14 +75,12 @@ def tools():
def index():
repo, host = settings.WEB_POI_REPO, settings.WEB_POI_HOST
result = storage.load_relative(repo, host, 0)
group_stats_result(result)
result1 = storage.load_relative(repo, host, 1)
group_stats_result(result1)
result2 = storage.load_all(repo, host)
return render_template("index.html",
visualzing=result,
changes=changes.compare(result, result1),
# timeline=None,
)
timeline=timeline.make_timeline(result2))
@click.command()
......
......@@ -13,8 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from mubench.frontend.utils import group_stats_result
def extract(tasksets):
def extract(op):
tasksets = op["ts"]
result = {}
for ts in tasksets:
result[ts["name"]] = ts["datapoints_grouped"]
......@@ -26,7 +29,7 @@ def compare_ts(op1, op2):
for impl in op1:
for metric in op1[impl]:
if impl in op2 and metric in op2[impl]:
if not impl in result:
if impl not in result:
result[impl] = {}
result[impl][metric] = op1[impl][metric].compare_obj(
op2[impl][metric])
......@@ -34,11 +37,13 @@ def compare_ts(op1, op2):
def compare(op1, op2):
extracted = extract(op1["ts"])
extracted1 = extract(op2["ts"])
group_stats_result(op1)
group_stats_result(op2)
extracted = extract(op1)
extracted1 = extract(op2)
result = {}
for ts_name in extracted:
if ts_name in extracted1:
result[ts_name] = compare_ts(extracted[ts_name],
extracted1[ts_name])
return result
\ No newline at end of file
return result
......@@ -29,7 +29,7 @@ class LocalStorage(Storage):
@classmethod
def load(cls, repo, host, rev):
dirname = cls.STORAGE_PATH / repo / host
filename = dirname.glob("{}*".format(rev))[0]
filename = dirname.glob("{}*".format(rev)).__next__()
with open(filename) as logfile:
return json.load(logfile)
......@@ -37,7 +37,7 @@ class LocalStorage(Storage):
def store(cls, repo, host, rev, timestamp, text_form):
dirname = cls.STORAGE_PATH / repo / host
filename = dirname / "{}_{}".format(rev, timestamp)
os.makedirs(os.path.dirname(filename), exist_ok=True)
os.makedirs(os.path.dirname(str(filename.absolute())), exist_ok=True)
with open(filename, "w") as logfile:
logfile.write(text_form)
......@@ -50,3 +50,15 @@ class LocalStorage(Storage):
filename = dirname / fs[-(1 + num)]
with open(filename) as logfile:
return json.load(logfile)
@classmethod
def load_all(cls, repo, host):
dirname = cls.STORAGE_PATH / repo / host
fs = sorted(
[f.stem for f in dirname.iterdir() if not f.stem.startswith(".")],
key=lambda x: int(x.split("_")[1]))
results = []
for f in fs:
with open(dirname / f) as logfile:
results.append(json.load(logfile))
return results
{% from "marcos.html" import responsive_header,responsive_footer %}
<div id="linePlot"></div>
<script>
{{ responsive_header("linePlot") }}
var data = [];
{% for keyname in timeline %}
var trace = {type: "scatter"};
var n = {{ timeline[keyname]|length }};
var x = Array.apply(null, {length: n}).map(Number.call, Number);
var y = {{ timeline[keyname] }};
trace["x"] = x;
trace["y"] = y;
trace["name"] = "{{ keyname }}";
data.push(trace);
{% endfor %}
Plotly.newPlot('linePlot', data);
{{ responsive_footer() }}
</script>
\ No newline at end of file
{% extends 'base.html' %}
{% from "visualize_marcos.html" import responsive_header,responsive_footer %}
{% from "marcos.html" import responsive_header,responsive_footer %}
{% block body %}
<div class="panel panel-info">
<div class="panel-heading">Platform information</div>
......
{% from "visualize_marcos.html" import responsive_header,responsive_footer %}
{% from "marcos.html" import responsive_header,responsive_footer %}
{% for ts in visualzing["ts"] %}
<div class="panel panel-primary col-sm-6">
<div class="panel-heading">{{ ts["name"] }}</div>
......
#!/usr/bin/env python3
# Copyright 2017 The Australian National University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from mubench.frontend.utils import group_stats_result
from collections import defaultdict
def extract(op):
tasksets = op["ts"]
result = {}
for ts in tasksets:
result[ts["name"]] = ts["datapoints_grouped"]
return result
def make_timeline(ops):
for op in ops:
group_stats_result(op)
extracts = [extract(x) for x in ops]
results = defaultdict(dict)
for (idx, x) in enumerate(extracts):
for ts in x:
for impl in x[ts]:
for metric in x[ts][impl]:
keyname = "{}/{}/{}".format(ts, impl, metric)
results[keyname][idx] = x[ts][impl][metric].mean
for k in results:
v = results[k]
collect_dict = [None] * len(extracts)
for k1, v1 in v.items():
collect_dict[k1] = v1
results[k] = collect_dict
return results
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment